package cn.ug.pay.web.controller;

import cn.ug.activity.bean.CouponMemberBean;
import cn.ug.bean.LoginBean;
import cn.ug.bean.base.*;
import cn.ug.bean.type.ResultType;
import cn.ug.config.CacheUtilsService;
import cn.ug.config.Config;
import cn.ug.config.FundRateConfig;
import cn.ug.core.SerializeObjectError;
import cn.ug.core.ensure.Ensure;
import cn.ug.core.login.LoginHelper;
import cn.ug.enums.OrderNOPrefixEnum;
import cn.ug.enums.ProductTypeEnum;
import cn.ug.enums.RateKeyEnum;
import cn.ug.feign.*;
import cn.ug.mall.bean.*;
import cn.ug.member.bean.response.MemberUserBean;
import cn.ug.member.mq.MemberPasswordStatusMQ;
import cn.ug.mq.DelayMessagePostProcessor;
import cn.ug.pay.bean.FrozenTbillBean;
import cn.ug.pay.bean.TbillCenterBean;
import cn.ug.pay.bean.TbillRecord;
import cn.ug.pay.bean.WaitingPayBean;
import cn.ug.pay.bean.enumeration.GoldBeanProportionEnum;
import cn.ug.pay.bean.enumeration.TbillStatusRemark;
import cn.ug.pay.bean.status.TbillStatusEnum;
import cn.ug.pay.mapper.entity.*;
import cn.ug.pay.service.*;
import cn.ug.product.bean.response.LeaseDay;
import cn.ug.product.bean.response.ProductFindBean;
import cn.ug.util.*;
import cn.ug.web.controller.BaseController;
import cn.ug.web.controller.ExportExcelController;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static cn.ug.config.QueueName.QUEUE_MEMBER_PASSWORD_STATUS_DELAY;
import static cn.ug.util.ConstantUtil.NORMAL_DATE_FORMAT;
import static java.math.BigDecimal.ROUND_HALF_UP;
import static org.springframework.web.bind.annotation.RequestMethod.GET;

@RestController
@RequestMapping("tbill")
public class PayTbillController extends BaseController {
    @Autowired
    private PayTbillService payTbillService;
    @Autowired
    private PayTbillStatusService payTbillStatusService;
    @Autowired
    private PayTbillLeasebackService payTbillLeasebackService;
    @Autowired
    private PayTbillSoldService payTbillSoldService;
    @Autowired
    private ProductService productService;
    @Autowired
    private PriceService priceService;
    @Autowired
    private MemberUserService memberUserService;
    @Autowired
    private RateSettingsService rateSettingsService;
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Autowired
    private PayTbillStatisticsService payTbillStatisticsService;
    @Autowired
    private CacheUtilsService cacheUtilsService;
    @Autowired
    private CouponRepertoryService couponRepertoryService;
    @Autowired
    private ExtractionGoldService extractionGoldService;
    @Autowired
    private FundRateConfig fundRateConfig;
    @Resource
    private Config config;

    private final static String TBILL_SOLD_KEY = "PayTbillController:tbill:sale:goldPrice:";
    private final static String EXPERIENCE_PAY_KEY = "PayTbillController:experience:pay:goldPrice:";

    @PostMapping("/read")
    public SerializeObject read(@RequestHeader String accessToken, String orderNO) {
        orderNO = UF.toString(orderNO);
        if (payTbillService.read(orderNO)) {
            return new SerializeObject(ResultType.NORMAL, "00000001");
        } else {
            return new SerializeObjectError("00000005");
        }
    }

    @PostMapping("/undetermined/read")
    public SerializeObject readAll(@RequestHeader String accessToken) {
        String memberId = LoginHelper.getLoginId();
        if (StringUtils.isBlank(memberId)) {
            return new SerializeObjectError("00000102");
        }
        if (payTbillService.readUndeterminedBills(memberId)) {
            return new SerializeObject(ResultType.NORMAL, "00000001");
        } else {
            return new SerializeObjectError("00000005");
        }
    }

    @GetMapping("/unread/num")
    public SerializeObject getUnreadNum(@RequestHeader String accessToken, int status) {
        String memberId = LoginHelper.getLoginId();
        if (StringUtils.isBlank(memberId)) {
            return new SerializeObjectError("00000102");
        }
        return new SerializeObject(ResultType.NORMAL, "00000001", payTbillService.countUnreadNum(memberId, status));
    }

    @GetMapping("/leaseback/with/tbillno")
    public SerializeObject getLeasebackInfo(@RequestHeader String accessToken, String tbillNO) {
        JSONObject result = new JSONObject();
        PayTbill payTbill = payTbillService.selectByOrderNO(tbillNO);
        if (payTbill != null) {
            result.put("productId", payTbill.getProductId());
            result.put("totalGram", payTbill.getTotalGram());
            PayTbillLeaseback payTbillLeaseback = payTbillLeasebackService.selectLatestByTbillNO(tbillNO);
            if (payTbillLeaseback != null) {
                result.put("orderNO", payTbillLeaseback.getOrderNO());
            }
        }
        return new SerializeObject(ResultType.NORMAL, "00000001", result);
    }

    @GetMapping("/effective/unread/num")
    public SerializeObject getUnreadNum(@RequestHeader String accessToken) {
        String memberId = LoginHelper.getLoginId();
        if (StringUtils.isBlank(memberId)) {
            return new SerializeObjectError("00000102");
        }
        return new SerializeObject(ResultType.NORMAL, "00000001", payTbillService.countUnreadNum(memberId, TbillStatusEnum.SOLD.getStatus()) + payTbillService.countUnreadNum(memberId, TbillStatusEnum.GOLD_EXTRACTION.getStatus()));
    }

    @GetMapping("/center/list")
    public SerializeObject<DataTable<TbillCenterBean>> getBillDataList(@RequestHeader String accessToken, Page page, Integer status) {
        status = status == null ? 2 : status;
        String memberId = LoginHelper.getLoginId();
        if (StringUtils.isBlank(memberId)) {
            return new SerializeObjectError("00000102");
        }
        int total = payTbillService.countForTbillCenter(memberId, status);
        page.setTotal(total);
        if (total > 0) {
            if (page.getPageNum() == 0) {
                List<TbillCenterBean> list = payTbillService.queryForTbillCenter(memberId, status, 0, 0);
                if (list != null && list.size() > 0) {
                    for (TbillCenterBean bean : list) {
                        bean.setStatus(status);
                    }
                }
                return new SerializeObject<>(ResultType.NORMAL, new DataTable<TbillCenterBean>(page.getPageNum(), page.getPageSize(), page.getTotal(), list));
            } else {
                List<TbillCenterBean> list = payTbillService.queryForTbillCenter(memberId, status, PaginationUtil.getOffset(page.getPageNum(), page.getPageSize()), PaginationUtil.getPageSize(page.getPageSize()));
                if (list != null && list.size() > 0) {
                    if (status != 7) {
                        for (TbillCenterBean bean : list) {
                            bean.setStatus(status);
                        }
                    }
                }
                return new SerializeObject<>(ResultType.NORMAL, new DataTable<TbillCenterBean>(page.getPageNum(), page.getPageSize(), page.getTotal(), list));
            }
        }
        return new SerializeObject<>(ResultType.NORMAL, new DataTable<TbillCenterBean>(page.getPageNum(), page.getPageSize(), page.getTotal(), new ArrayList<TbillCenterBean>()));

    }

    /**
     * 砸金蛋接口获取分享者购买的实物金信息
     *
     * @param orderNo
     * @return
     */
    @GetMapping("/query/record")
    public SerializeObject queryRecord(String orderNo) {
        return new SerializeObject<>(ResultType.NORMAL, payTbillService.queryForTbillList(orderNo));
    }

    @GetMapping("/center")
    public SerializeObject getBillData(@RequestHeader String accessToken) {
        String memberId = LoginHelper.getLoginId();
        if (StringUtils.isBlank(memberId)) {
            return new SerializeObjectError("00000102");
        }
        JSONObject result = new JSONObject();
        PayTbillStatistics payTbillStatistics = payTbillStatisticsService.selectByMemberId(memberId);
        if (payTbillStatistics != null) {
            result.put("bills", payTbillStatistics.getPendingGram() + payTbillStatistics.getLeasebackGram() + payTbillStatistics.getFrozenGram());
            result.put("rewards", BigDecimalUtil.to5Point(payTbillStatistics.getLeasebackIncomeAmount().add(payTbillStatistics.getIncomeAmount())));
            result.put("totalGram", payTbillStatistics.getTotalGram());
            result.put("soldGram", payTbillStatistics.getSoldGram());
            result.put("extractedGram", payTbillStatistics.getExtractedGram());
        } else {
            result.put("bills", 0);
            result.put("rewards", 0);
            result.put("totalGram", 0);
            result.put("soldGram", 0);
            result.put("extractedGram", 0);
        }
        return new SerializeObject<>(ResultType.NORMAL, "00000001", result);
    }

    @GetMapping("/coupon/lock")
    public SerializeObject getLockDays(@RequestHeader String accessToken, String orderNO) {
        orderNO = UF.toString(orderNO);
        String memberId = LoginHelper.getLoginId();
        if (StringUtils.isBlank(memberId)) {
            return new SerializeObjectError("00000102");
        }
        PayTbill payTbill = payTbillService.selectByOrderNO(orderNO);
        if (payTbill == null) {
            return new SerializeObjectError("00000003");
        }
        long days = 0;
        long hours = 0;
        if (StringUtils.isNotBlank(payTbill.getCouponId())) {
            if (payTbill.getLeasebackTimes() == 0) {
                LocalDateTime startTime = UF.getDateTime(payTbill.getAddTime());
                LocalDateTime endTime = LocalDateTime.now();
                Duration duration = Duration.between(startTime, endTime);
                days = duration.toDays();
                days = 30 - days;
                if (days < 0) {
                    days = 0;
                }
                hours = duration.toHours();
                hours = 30 * 24 - hours;
                if (hours < 0) {
                    hours = 0;
                }
            }
        }
        JSONObject result = new JSONObject();
        result.put("days", days);
        result.put("hours", hours);
        return new SerializeObject<>(ResultType.NORMAL, "00000001", result);
    }

    @GetMapping("/sale/calculation")
    public SerializeObject calculateImcome(@RequestHeader String accessToken, String orderNO) {
        orderNO = UF.toString(orderNO);
        String memberId = LoginHelper.getLoginId();
        if (StringUtils.isBlank(memberId)) {
            return new SerializeObjectError("00000102");
        }
        PayTbill payTbill = payTbillService.selectByOrderNO(orderNO);
        if (payTbill == null) {
            return new SerializeObjectError("00000003");
        }
        String hashKey = TBILL_SOLD_KEY + orderNO;
        SerializeObject serializeObject = priceService.currentGoldPrice();
        if (null == serializeObject || serializeObject.getCode() != ResultType.NORMAL) {
            Ensure.that(true).isTrue("17000708");
        }
        BigDecimal couponAmount = BigDecimal.ZERO;
        if (StringUtils.isNotBlank(payTbill.getCouponId())) {
            if (payTbill.getLeasebackTimes() == 0) {
                LocalDateTime startTime = UF.getDateTime(payTbill.getAddTime());
                LocalDateTime endTime = LocalDateTime.now();
                Duration duration = Duration.between(startTime, endTime);
                long days = duration.toDays();
                //long hours = duration.toHours();
                if (days < 30) {
                    couponAmount = payTbill.getCouponGram().multiply(payTbill.getGoldPrice());
                }
            }
        }
        BigDecimal currentGoldPrice = new BigDecimal(serializeObject.getData().toString());
        cacheUtilsService.setCache(hashKey, currentGoldPrice);
        JSONObject result = new JSONObject();
        BigDecimal fee = payTbillSoldService.getFee(memberId, new BigDecimal(payTbill.getTotalGram()), currentGoldPrice);
        result.put("totalAmount", BigDecimalUtil.to2Point(new BigDecimal(payTbill.getTotalGram()).multiply(currentGoldPrice)));
        result.put("fee", fee);
        result.put("actualAmount", BigDecimalUtil.to2Point(new BigDecimal(payTbill.getTotalGram()).multiply(currentGoldPrice).subtract(fee).subtract(couponAmount)));
        result.put("couponAmount", couponAmount);
        return new SerializeObject<>(ResultType.NORMAL, "00000001", result);
    }

    @PostMapping("/sale")
    public SerializeObject sale(@RequestHeader String accessToken, String orderNO, String payPassword) {
        if (StringUtils.isBlank(orderNO) || StringUtils.isBlank(payPassword)) {
            return new SerializeObjectError("00000002");
        }
        orderNO = UF.toString(orderNO);
        payPassword = UF.toString(payPassword);
        LoginBean loginBean = LoginHelper.getLoginBean();
        if (loginBean == null || StringUtils.isBlank(loginBean.getAccessToken()) || !StringUtils.equals(accessToken, loginBean.getAccessToken())) {
            return new SerializeObject<>(ResultType.UNLOGIN, "00000102");
        }
        String memberId = LoginHelper.getLoginId();
        if (StringUtils.isBlank(memberId)) {
            return new SerializeObjectError("00000102");
        }
        SerializeObject obj = memberUserService.validatePayPassword(memberId, payPassword);
        if (null == obj || obj.getCode() != ResultType.NORMAL) {
            SerializeObject paramBean = rateSettingsService.get(RateKeyEnum.TRADE_PASSWORD.getKey());
            if (paramBean != null && paramBean.getData() != null) {
                JSONObject json = JSON.parseObject(JSONObject.toJSONString(paramBean.getData()));
                int isLimited = json.getIntValue("isLimited");
                int wrongTimes = json.getIntValue("wrongTimes");
                int minutes = json.getIntValue("minutes");
                if (isLimited == 1) {
                    SerializeObject<MemberUserBean> memberBean = memberUserService.findById(memberId);
                    if (null == memberBean || memberBean.getData() == null) {
                        return new SerializeObjectError("00000102");
                    }
                    MemberUserBean memberUserBean = memberBean.getData();
                    if (isLimited == 1 && memberUserBean.getTrdpassdStatus() == 1) {
                        SerializeObjectError result = new SerializeObjectError<>("17002034");
                        String msg = String.format(result.getMsg(), wrongTimes, minutes);
                        result.setMsg(msg);
                        return result;
                    }
                    int actualWrongTimes = memberUserBean.getTrdpassdWrongTimes();
                    actualWrongTimes++;
                    int status = 0;
                    if (wrongTimes <= actualWrongTimes) {
                        status = 1;
                    }
                    memberUserService.modifyWrongTimes(memberUserBean.getId(), 2, actualWrongTimes, status);
                    if (wrongTimes <= actualWrongTimes) {
                        MemberPasswordStatusMQ mq = new MemberPasswordStatusMQ();
                        mq.setMemberId(memberUserBean.getId());
                        mq.setType(2);
                        amqpTemplate.convertAndSend(QUEUE_MEMBER_PASSWORD_STATUS_DELAY, mq, new DelayMessagePostProcessor(minutes * 60 * 1000));

                        SerializeObjectError result = new SerializeObjectError<>("17002034");
                        String msg = String.format(result.getMsg(), wrongTimes, minutes);
                        result.setMsg(msg);
                        return result;
                    }
                }
            }
            return new SerializeObjectError<>("17000409");
        }
        memberUserService.modifyWrongTimes(memberId, 2, 0, 0);
        String saleNO = payTbillSoldService.sale(orderNO, TBILL_SOLD_KEY);
        if (StringUtils.isNotBlank(saleNO)) {
            return new SerializeObject(ResultType.NORMAL, "00000001", saleNO);
        } else {
            return new SerializeObjectError("00000005");
        }
    }

    @GetMapping("/discount")
    public SerializeObject getBuyGoldDiscount(@RequestHeader String accessToken, String productId, int totalGram) {
        if (StringUtils.isBlank(productId) && totalGram < 1) {
            return new SerializeObjectError("00000002");
        }
        String memberId = LoginHelper.getLoginId();
        if (StringUtils.isBlank(memberId)) {
            return new SerializeObjectError("00000102");
        }
        SerializeObject<ProductFindBean> obj = productService.queryProductById(productId);
        if (null == obj || obj.getCode() != ResultType.NORMAL || obj.getData() == null) {
            Ensure.that(true).isTrue("17000601");
        }
        ProductFindBean productBean = obj.getData();
        BigDecimal goldPrice = BigDecimal.ZERO;
        if (1 == productBean.getSettingPriceType()) {
            SerializeObject serializeObject = priceService.currentGoldPrice();
            if (null == serializeObject || serializeObject.getCode() != ResultType.NORMAL) {
                Ensure.that(true).isTrue("17000708");
            }
            goldPrice = new BigDecimal(serializeObject.getData().toString());
        } else {
            goldPrice = productBean.getSettingPrice();
        }
        JSONObject result = new JSONObject();
        int successfulNum = payTbillService.countSuccessfulNum(memberId);
        BigDecimal discountAmount = BigDecimal.ZERO;
        int firstAmountType = 1;
        if (successfulNum == 0 && totalGram >= 1) {
            SerializeObject rateBean = rateSettingsService.get(RateKeyEnum.BUY_GOLD_PRIVILEGE.getKey());
            if (rateBean != null && rateBean.getData() != null) {
                GoldPrivilegeBean bean = JSON.parseObject(JSONObject.toJSONString(rateBean.getData()), GoldPrivilegeBean.class);
                if (bean != null && bean.getType() == 2) {
                    if (bean.getPrivilegeType() != null && bean.getPrivilegeType() == 1) {
                        firstAmountType = 1;
                    }
                    if (bean.getPrivilegeType() != null && bean.getPrivilegeType() == 2) {
                        firstAmountType = 2;
                    }
                }
                discountAmount = fundRateConfig.getFirstAmount(bean, totalGram);
            }
        }
        discountAmount = discountAmount == null ? BigDecimal.ZERO : discountAmount;
        result.put("firstAmount", discountAmount);
        result.put("firstAmountType", firstAmountType);

        discountAmount = BigDecimal.ZERO;
        SerializeObject discountRateBean = rateSettingsService.findONTemplateByType(1);
        int discountAmountType = 1;
        if (discountRateBean != null && discountRateBean.getData() != null) {
            PrivilegeTemplateBean bean = JSON.parseObject(JSONObject.toJSONString(discountRateBean.getData()), PrivilegeTemplateBean.class);
            if (bean != null) {
                if (bean.getWay() != null) {
                    discountAmountType = bean.getWay();
                }
            }
            if (discountAmountType == 1) {
                discountAmount = fundRateConfig.getDiscountAmount(bean, new BigDecimal(totalGram), 0);
            } else if (discountAmountType == 2) {
                discountAmount = fundRateConfig.getDiscountAmount(bean, new BigDecimal(totalGram), 0);
            } else if (discountAmountType == 3) {
                discountAmount = fundRateConfig.getDiscountAmount(bean, new BigDecimal(totalGram), 0);
            }
        }
        result.put("discountAmount", discountAmount);
        result.put("discountAmountType", discountAmountType);

        return new SerializeObject<>(ResultType.NORMAL, "00000001", result);
    }

    @GetMapping("/experience/calculation")
    public SerializeObject calculateImcome(@RequestHeader String accessToken, String productId, int totalGram) {
        if (StringUtils.isBlank(productId) || totalGram < 1) {
            return new SerializeObjectError("00000002");
        }
        String memberId = LoginHelper.getLoginId();
        if (StringUtils.isBlank(memberId)) {
            return new SerializeObjectError("00000102");
        }
        SerializeObject<ProductFindBean> obj = productService.queryProductById(productId);
        if (null == obj || obj.getCode() != ResultType.NORMAL || obj.getData() == null) {
            Ensure.that(true).isTrue("17000601");
        }
        ProductFindBean productBean = obj.getData();
        if (productBean.getLeaseDayList() == null || productBean.getLeaseDayList().size() == 0) {
            Ensure.that(true).isTrue("00000002");
        }
        BigDecimal actualGoldPrice = BigDecimal.ZERO;
        if (1 == productBean.getSettingPriceType()) {
            SerializeObject serializeObject = priceService.currentGoldPrice();
            if (null == serializeObject || serializeObject.getCode() != ResultType.NORMAL) {
                Ensure.that(true).isTrue("17000708");
            }
            actualGoldPrice = new BigDecimal(serializeObject.getData().toString());
        } else {
            actualGoldPrice = productBean.getSettingPrice();
        }
        String hashKey = EXPERIENCE_PAY_KEY + memberId;
        cacheUtilsService.setCache(hashKey, actualGoldPrice);
        BigDecimal income = calculateIncomeAmount(new BigDecimal(totalGram), productBean.getLeaseDayList().get(0).getLeaseDay(), productBean.getLeaseDayList().get(0).getYearsIncome());
        LocalDateTime startTime = UF.getDateTime().plusDays(productBean.getInterestAccrualDay());
        LocalDateTime endTime = startTime.plusDays(productBean.getLeaseDayList().get(0).getLeaseDay());
        JSONObject result = new JSONObject();
        if (productBean.getLeaseCloseType() != null && productBean.getLeaseCloseType() == 1) {
            result.put("incomeAmount", BigDecimalUtil.to2Point(actualGoldPrice.multiply(income)));
        }
        if (productBean.getLeaseCloseType() != null && productBean.getLeaseCloseType() == 2) {
            result.put("incomeAmount", income.multiply(new BigDecimal(10000)).intValue());
        }
        result.put("endTime", UF.getFormatDateTime(endTime));
        return new SerializeObject<>(ResultType.NORMAL, "00000001", result);
    }

    @PostMapping("/experience/pay")
    public SerializeObject pay(@RequestHeader String accessToken, String productId, int totalGram) {
        if (StringUtils.isBlank(productId) || totalGram < 1) {
            return new SerializeObjectError("00000002");
        }
        LoginBean loginBean = LoginHelper.getLoginBean();
        if (loginBean == null || StringUtils.isBlank(loginBean.getAccessToken()) || !StringUtils.equals(accessToken, loginBean.getAccessToken())) {
            return new SerializeObject<>(ResultType.UNLOGIN, "00000102");
        }
        String memberId = LoginHelper.getLoginId();
        if (StringUtils.isBlank(memberId)) {
            return new SerializeObjectError("00000102");
        }
        String hashKey = EXPERIENCE_PAY_KEY + memberId;
        Object cacheGoldPrice = cacheUtilsService.getCache(hashKey);
        if (null == cacheGoldPrice) {
            Ensure.that(true).isTrue("00000005");
        }
        BigDecimal goldPrice = new BigDecimal(cacheGoldPrice.toString());
        String saleNO = payTbillService.saveExperienceOrder(memberId, productId, totalGram, goldPrice, hashKey);
        if (StringUtils.isNotBlank(saleNO)) {
            return new SerializeObject(ResultType.NORMAL, "00000001", saleNO);
        } else {
            return new SerializeObjectError("00000005");
        }
    }

    /**
     * 获取回租金价
     *
     * @param orderNo
     * @return
     */
    @GetMapping("query/leasebackPrice")
    private SerializeObject queryLeasebackPrice(String orderNo) {
        PayTbill payTbill = payTbillService.selectByOrderNO(orderNo);
        if (payTbill == null) {
            return new SerializeObjectError("00000003");
        }
        SerializeObject<ProductFindBean> productFindBean = productService.queryProductById(payTbill.getProductId());
        if (null == productFindBean || productFindBean.getCode() != ResultType.NORMAL) {
            return new SerializeObjectError("00000005");
        }

        ProductFindBean productBean = productFindBean.getData();
        if (productBean == null || productBean.getLeaseDayList() == null || productBean.getLeaseDayList().size() == 0) {
            return new SerializeObjectError("00000003");
        }
        Integer leaseCalculateGoldType = productBean.getLeaseCalculateGoldType();
        leaseCalculateGoldType = leaseCalculateGoldType == null ? 1 : leaseCalculateGoldType;
        String point = "";
        if (leaseCalculateGoldType == 1) {
            point = "02:30";
        } else {
            point = productBean.getLeaseCalculateGoldTime();
        }
        SimpleDateFormat format = new SimpleDateFormat(NORMAL_DATE_FORMAT);
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, -1);
        String someday = format.format(calendar.getTime()) + " " + point;
        SerializeObject<Double> result = priceService.getSomedayPrice(someday);
        return new SerializeObject(ResultType.NORMAL, "00000001", result.getData());
    }


    /**
     * 提单回租
     *
     * @param accessToken
     * @param orderNO
     * @param leaseId
     * @param couponId
     * @param payPassword
     * @return
     */
    @PostMapping("/leaseback")
    public SerializeObject update(@RequestHeader String accessToken, String orderNO, int leaseId, String couponId, String payPassword) {
        if (StringUtils.isBlank(orderNO) || leaseId < 1 || StringUtils.isBlank(payPassword)) {
            return new SerializeObjectError("00000002");
        }
        couponId = UF.toString(couponId);
        LoginBean loginBean = LoginHelper.getLoginBean();
        if (loginBean == null || StringUtils.isBlank(loginBean.getAccessToken()) || !StringUtils.equals(accessToken, loginBean.getAccessToken())) {
            return new SerializeObject<>(ResultType.UNLOGIN, "00000102");
        }
        String memberId = LoginHelper.getLoginId();
        if (StringUtils.isBlank(memberId)) {
            return new SerializeObjectError("00000102");
        }
        SerializeObject obj = memberUserService.validatePayPassword(memberId, payPassword);
        if (null == obj || obj.getCode() != ResultType.NORMAL) {
            SerializeObject paramBean = rateSettingsService.get(RateKeyEnum.TRADE_PASSWORD.getKey());
            if (paramBean != null && paramBean.getData() != null) {
                JSONObject json = JSON.parseObject(JSONObject.toJSONString(paramBean.getData()));
                int isLimited = json.getIntValue("isLimited");
                int wrongTimes = json.getIntValue("wrongTimes");
                int minutes = json.getIntValue("minutes");
                if (isLimited == 1) {
                    SerializeObject<MemberUserBean> memberBean = memberUserService.findById(memberId);
                    if (null == memberBean || memberBean.getData() == null) {
                        return new SerializeObjectError("00000102");
                    }
                    MemberUserBean memberUserBean = memberBean.getData();
                    if (isLimited == 1 && memberUserBean.getTrdpassdStatus() == 1) {
                        SerializeObjectError result = new SerializeObjectError<>("17002034");
                        String msg = String.format(result.getMsg(), wrongTimes, minutes);
                        result.setMsg(msg);
                        return result;
                    }
                    int actualWrongTimes = memberUserBean.getTrdpassdWrongTimes();
                    actualWrongTimes++;
                    int status = 0;
                    if (wrongTimes <= actualWrongTimes) {
                        status = 1;
                    }
                    memberUserService.modifyWrongTimes(memberUserBean.getId(), 2, actualWrongTimes, status);
                    if (wrongTimes <= actualWrongTimes) {
                        MemberPasswordStatusMQ mq = new MemberPasswordStatusMQ();
                        mq.setMemberId(memberUserBean.getId());
                        mq.setType(2);
                        amqpTemplate.convertAndSend(QUEUE_MEMBER_PASSWORD_STATUS_DELAY, mq, new DelayMessagePostProcessor(minutes * 60 * 1000));

                        SerializeObjectError result = new SerializeObjectError<>("17002034");
                        String msg = String.format(result.getMsg(), wrongTimes, minutes);
                        result.setMsg(msg);
                        return result;
                    }
                }
            }
            return new SerializeObjectError<>("17000409");
        }
        memberUserService.modifyWrongTimes(memberId, 2, 0, 0);
        PayTbill payTbill = payTbillService.selectByOrderNO(orderNO);
        if (payTbill == null) {
            return new SerializeObjectError("00000003");
        }
        SerializeObject<ProductFindBean> productFindBean = productService.queryProductById(payTbill.getProductId());
        if (null == productFindBean || productFindBean.getCode() != ResultType.NORMAL) {
            return new SerializeObjectError("00000005");
        }

        ProductFindBean productBean = productFindBean.getData();
        if (productBean == null || productBean.getLeaseDayList() == null || productBean.getLeaseDayList().size() == 0) {
            return new SerializeObjectError("00000003");
        }
        Integer leaseCalculateGoldType = productBean.getLeaseCalculateGoldType();
        leaseCalculateGoldType = leaseCalculateGoldType == null ? 1 : leaseCalculateGoldType;
        String point = "";
        if (leaseCalculateGoldType == 1) {
            point = "02:30";
        } else {
            point = productBean.getLeaseCalculateGoldTime();
        }
        SimpleDateFormat format = new SimpleDateFormat(NORMAL_DATE_FORMAT);
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, -1);
        String someday = format.format(calendar.getTime()) + " " + point;
        SerializeObject<Double> result = priceService.getSomedayPrice(someday);
        if (result != null) {
            double price = result.getData();
            List<LeaseDay> leaseDayList = productBean.getLeaseDayList();
            LeaseDay readlLeaseDay = null;
            for (LeaseDay leaseDay : leaseDayList) {
                if (leaseDay.getId() == leaseId) {
                    readlLeaseDay = leaseDay;
                    break;
                }
            }
            if (readlLeaseDay == null) {
                return new SerializeObjectError("00000002");
            }
            BigDecimal income = calculateIncomeAmount(new BigDecimal(payTbill.getTotalGram()), readlLeaseDay.getLeaseDay(), readlLeaseDay.getYearsIncome());
            PayTbillLeaseback payTbillLeaseback = new PayTbillLeaseback();
            payTbillLeaseback.setTbillNO(orderNO);
            Integer incomeType = productBean.getLeaseCloseType();
            incomeType = incomeType == null ? 1 : incomeType;
            payTbillLeaseback.setIncomeType(incomeType);
            payTbillLeaseback.setOrderNO(OrderNOPrefixEnum.LB.name() + SerialNumberWorker.getInstance().nextId());

            LocalDateTime startTime = UF.getDateTime(UF.getFormatDateNow()).plusDays(productBean.getInterestAccrualDay());
            LocalDateTime endTime = startTime.plusDays(readlLeaseDay.getLeaseDay());
            payTbillLeaseback.setStartTime(UF.getFormatDateTime(UF.getDateTime()));
            payTbillLeaseback.setEndTime(UF.getFormatDateTime(endTime));
            payTbillLeaseback.setGoldPrice(new BigDecimal(price));
            payTbillLeaseback.setLeasebackDays(readlLeaseDay.getLeaseDay());
            payTbillLeaseback.setYearIncome(readlLeaseDay.getYearsIncome());
            //回租收益（克）
            payTbillLeaseback.setIncomeGram(income);
            int beans = (int) Math.round(income.multiply(new BigDecimal(GoldBeanProportionEnum.PROPORTION.getValue())).doubleValue());
            payTbillLeaseback.setIncomeBeans(beans);
            //回租收益（元） 40 回租金生金奖励 + 黄金红包奖励
            //payTbillLeaseback.setIncomeAmount(BigDecimalUtil.to2Point(income.multiply(new BigDecimal(price))));
            payTbillLeaseback.setIncomeAmount(BigDecimalUtil.to2Point(income.multiply(new BigDecimal(price))));
            //金生金奖励
            payTbillLeaseback.setGoldGiveGoldAmount(payTbillLeaseback.getIncomeAmount());
            if (StringUtils.isNotBlank(couponId) && !StringUtils.equals(couponId, "0")) {
                SerializeObject<CouponMemberBean> couponBean = couponRepertoryService.getMemberCoupon(couponId);
                if (couponBean == null || couponBean.getData() == null || couponBean.getData().getStatus() != 1 || couponBean.getData().getTransactionAmount() > payTbill.getTotalGram()
                        || couponBean.getData().getLeasebackDays() > payTbillLeaseback.getLeasebackDays()) {
                    return new SerializeObjectError("00000005");
                }
                payTbillLeaseback.setCouponId(couponId);
                //红包卷类型 0黄金红包 1回租卷  2.商城卷
                payTbillLeaseback.setCouponType(couponBean.getData().getType());
                //黄金红包奖励
                payTbillLeaseback.setCouponAwardAmount(BigDecimalUtil.to2Point(new BigDecimal(couponBean.getData().getDiscountAmount()).divide(new BigDecimal(1000)).multiply(new BigDecimal(price))));
                payTbillLeaseback.setIncomeAmount(payTbillLeaseback.getIncomeAmount().add(payTbillLeaseback.getCouponAwardAmount()));
                payTbillLeaseback.setCouponAmount(couponBean.getData().getDiscountAmount());
                //回租福利卷 减时卷  当前已不再使用
                if (couponBean.getData().getType() == 1) {
                    LocalDateTime actualTime = endTime.plusDays(-couponBean.getData().getDiscountAmount());
                    payTbillLeaseback.setActualTime(UF.getFormatDateTime(actualTime));
                } else {
                    payTbillLeaseback.setActualTime(UF.getFormatDateTime(endTime));
                }
                //todo 回租福利卷换成了黄金红包卷就没有了这个福利券对应年化  切换成金生金加息年化
                //BigDecimal couponYearIncome = BigDecimalUtil.to2Point(payTbillLeaseback.getYearIncome().multiply(new BigDecimal(payTbillLeaseback.getLeasebackDays()*1.0/(payTbillLeaseback.getLeasebackDays() - couponBean.getData().getDiscountAmount()) - 1)));
                payTbillLeaseback.setCouponYearIncome(couponBean.getData().getRaiseYearIncome());
            } else {
                payTbillLeaseback.setCouponId("");
                payTbillLeaseback.setActualTime(UF.getFormatDateTime(endTime));
                payTbillLeaseback.setCouponYearIncome(BigDecimal.ZERO);
                payTbillLeaseback.setCouponAmount(0);
            }
            BigDecimal discountAmount = BigDecimal.ZERO;
            SerializeObject discountRateBean = rateSettingsService.findONTemplateByType(2);
            int discountAmountType = 1;
            if (discountRateBean != null && discountRateBean.getData() != null) {
                PrivilegeTemplateBean bean = JSON.parseObject(JSONObject.toJSONString(discountRateBean.getData()), PrivilegeTemplateBean.class);
                if (bean != null && bean.getWay() != null) {
                    discountAmountType = bean.getWay();
                }
                getLog().info("回租奖励模板：" + JSON.toJSONString(bean));
                discountAmount = fundRateConfig.getDiscountAmount(bean, new BigDecimal(payTbillLeaseback.getLeasebackDays()), 1);
                getLog().info("回租奖励数量：" + discountAmount);
            }
            if (discountAmountType == 3) {
                discountAmount = new BigDecimal(discountAmount.intValue());
            }
            payTbillLeaseback.setDiscountAmount(discountAmount);
            payTbillLeaseback.setDiscountAmountType(discountAmountType);
            if (payTbillLeasebackService.save(payTbillLeaseback)) {
                return new SerializeObject(ResultType.NORMAL, "00000001", payTbillLeaseback.getOrderNO());
            } else {
                return new SerializeObjectError("00000005");
            }
        } else {
            return new SerializeObjectError("00000005");
        }
    }

    @GetMapping("/leaseback/discount")
    public SerializeObject getDiscount(@RequestHeader String accessToken, String orderNO, int leasebackDays) {
        if (leasebackDays < 1) {
            return new SerializeObjectError("00000002");
        }
        /*if (StringUtils.isBlank(orderNO) || leasebackDays < 1) {
            return new SerializeObjectError("00000002");
        }
        PayTbill payTbill = payTbillService.selectByOrderNO(orderNO);
        if (payTbill == null) {
            return new SerializeObjectError("00000003");
        }*/
        BigDecimal discountAmount = BigDecimal.ZERO;
        SerializeObject discountRateBean = rateSettingsService.findONTemplateByType(2);
        int discountAmountType = 1;
        if (discountRateBean != null && discountRateBean.getData() != null) {
            PrivilegeTemplateBean bean = JSON.parseObject(JSONObject.toJSONString(discountRateBean.getData()), PrivilegeTemplateBean.class);
            if (bean != null && bean.getWay() != null) {
                discountAmountType = bean.getWay();
            }
            discountAmount = fundRateConfig.getDiscountAmount(bean, new BigDecimal(leasebackDays), 1);
        }
        if (discountAmountType == 1) {
            return new SerializeObject(ResultType.NORMAL, "00000001", discountAmount);
        } else {
            return new SerializeObject(201, "00000001", discountAmount);
        }
    }

    @GetMapping("/leaseday")
    public SerializeObject getLeaseday(@RequestHeader String accessToken, String orderNO) {
        PayTbill payTbill = payTbillService.selectByOrderNO(orderNO);
        if (payTbill == null) {
            return new SerializeObjectError("00000003");
        }
        SerializeObject<ProductFindBean> productFindBean = productService.queryProductById(payTbill.getProductId());
        if (null == productFindBean || productFindBean.getCode() != ResultType.NORMAL) {
            return new SerializeObjectError("00000005");
        }
        ProductFindBean productBean = productFindBean.getData();
        if (productBean == null || productBean.getLeaseDayList() == null || productBean.getLeaseDayList().size() == 0) {
            return new SerializeObjectError("00000003");
        }
        Integer leaseCalculateGoldType = productBean.getLeaseCalculateGoldType();
        leaseCalculateGoldType = leaseCalculateGoldType == null ? 1 : leaseCalculateGoldType;
        String point = "";
        if (leaseCalculateGoldType == 1) {
            point = "02:30";
        } else {
            point = productBean.getLeaseCalculateGoldTime();
        }
        SimpleDateFormat format = new SimpleDateFormat(NORMAL_DATE_FORMAT);
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, -1);
        String someday = format.format(calendar.getTime()) + " " + point;
        SerializeObject<Double> result = priceService.getSomedayPrice(someday);
        if (result != null) {
            double price = result.getData();
            List<LeaseDay> leaseDayList = productBean.getLeaseDayList();
            for (LeaseDay leaseDay : leaseDayList) {
                if (productBean.getLeaseCloseType() != null && productBean.getLeaseCloseType() == 1) {
                    BigDecimal income = calculateIncomeAmount(new BigDecimal(payTbill.getTotalGram()), leaseDay.getLeaseDay(), leaseDay.getYearsIncome().multiply(new BigDecimal(price)));
                    leaseDay.setIncomeAmount(BigDecimalUtil.to2Point(income));
                    leaseDay.setIncomeType(productBean.getLeaseCloseType());
                }
                if (productBean.getLeaseCloseType() != null && productBean.getLeaseCloseType() == 2) {
                    BigDecimal income = calculateIncomeAmount(new BigDecimal(payTbill.getTotalGram()), leaseDay.getLeaseDay(), leaseDay.getYearsIncome());
                    int beans = (int) Math.round(income.multiply(new BigDecimal(GoldBeanProportionEnum.PROPORTION.getValue())).doubleValue());
                    leaseDay.setIncomeAmount(new BigDecimal(beans));
                    leaseDay.setIncomeType(productBean.getLeaseCloseType());
                }
            }
            return new SerializeObject<>(ResultType.NORMAL, "00000001", leaseDayList);
        } else {
            return new SerializeObjectError("00000005");
        }
    }

    @GetMapping("/leaseday/list")
    public SerializeObject getLeaseday(@RequestHeader String accessToken, String productId, int totalGram) {
        SerializeObject<ProductFindBean> productFindBean = productService.queryProductById(productId);
        if (null == productFindBean || productFindBean.getCode() != ResultType.NORMAL) {
            return new SerializeObjectError("00000005");
        }
        ProductFindBean productBean = productFindBean.getData();
        if (productBean == null || productBean.getLeaseDayList() == null || productBean.getLeaseDayList().size() == 0) {
            return new SerializeObjectError("00000003");
        }
        Integer leaseCalculateGoldType = productBean.getLeaseCalculateGoldType();
        leaseCalculateGoldType = leaseCalculateGoldType == null ? 1 : leaseCalculateGoldType;
        String point = "";
        if (leaseCalculateGoldType == 1) {
            point = "02:30";
        } else {
            point = productBean.getLeaseCalculateGoldTime();
        }
        SimpleDateFormat format = new SimpleDateFormat(NORMAL_DATE_FORMAT);
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, -1);
        String someday = format.format(calendar.getTime()) + " " + point;
        SerializeObject<Double> result = priceService.getSomedayPrice(someday);
        if (result != null) {
            double price = result.getData();
            List<LeaseDay> leaseDayList = productBean.getLeaseDayList();
            for (LeaseDay leaseDay : leaseDayList) {
                if (productBean.getLeaseCloseType() != null && productBean.getLeaseCloseType() == 1) {
                    BigDecimal income = calculateIncomeAmount(new BigDecimal(totalGram), leaseDay.getLeaseDay(), leaseDay.getYearsIncome().multiply(new BigDecimal(price)));
                    leaseDay.setIncomeAmount(BigDecimalUtil.to2Point(income));
                    leaseDay.setIncomeType(productBean.getLeaseCloseType());
                }
                if (productBean.getLeaseCloseType() != null && productBean.getLeaseCloseType() == 2) {
                    BigDecimal income = calculateIncomeAmount(new BigDecimal(totalGram), leaseDay.getLeaseDay(), leaseDay.getYearsIncome());
                    int beans = (int) Math.round(income.multiply(new BigDecimal(GoldBeanProportionEnum.PROPORTION.getValue())).doubleValue());
                    leaseDay.setIncomeAmount(new BigDecimal(beans));
                    leaseDay.setIncomeType(productBean.getLeaseCloseType());
                }
            }
            return new SerializeObject<>(ResultType.NORMAL, "00000001", leaseDayList);
        } else {
            return new SerializeObjectError("00000005");
        }
    }


    /**
     * 查询实物金和折扣金产品的回租期限
     *
     * @return
     */
    @GetMapping("/query/leasedays")
    public SerializeObject getLeasedays() {
        List<Integer> leaseDayList = null;
        SerializeObject obj = rateSettingsService.get(RateKeyEnum.ENTITY_GOLD.getKey());
        if (obj != null && obj.getData() != null) {

            JSONObject jsonObject = (JSONObject) JSONObject.toJSON(obj.getData());
            EntityGoldBean entityGoldBean = JSONObject.toJavaObject(jsonObject, EntityGoldBean.class);
            if (!CollectionUtils.isEmpty(entityGoldBean.getLeaseDayList())) {
                leaseDayList = entityGoldBean.getLeaseDayList().stream().map(o -> o.getLeaseDay()).collect(Collectors.toList());
            }
        }


        List<Integer> leaseDayList2 = null;
        SerializeObject obj2 = rateSettingsService.get(RateKeyEnum.DISCOUNT_GOLD.getKey());
        if (obj2 != null && obj2.getData() != null) {
            JSONObject jsonObject = (JSONObject) JSONObject.toJSON(obj2.getData());
            DiscountGoldBean discountGoldBean = JSONObject.toJavaObject(jsonObject, DiscountGoldBean.class);
            if (!CollectionUtils.isEmpty(discountGoldBean.getLeaseDayList())) {
                leaseDayList2 = discountGoldBean.getLeaseDayList().stream().map(o -> o.getLeaseDay()).collect(Collectors.toList());
            }
        }

        List<Integer> resultList = Stream.of(leaseDayList, leaseDayList2)
                .flatMap(Collection::stream)
                .distinct()
                .collect(Collectors.toList());
        resultList.sort(Comparator.comparing(Integer::intValue));
        return new SerializeObject<>(ResultType.NORMAL, "00000001", resultList);
    }


    private BigDecimal calculateIncomeAmount(BigDecimal weight, int investDay, BigDecimal yearsIncome) {
        if (BigDecimalUtil.isZeroOrNull(weight) || investDay < 0 || BigDecimalUtil.isZeroOrNull(yearsIncome)) {
            return BigDecimal.ZERO;
        }
        // 收益计算公式 = 购买克重 * 投资期限 * 年化收益 / 100 / 365
        // *投资期限
        BigDecimal income = weight.multiply(new BigDecimal(investDay));
        // *年化收益/100/365
        income = income.multiply(yearsIncome);
        income = income.divide(new BigDecimal("100"), 10, ROUND_HALF_UP);
        income = income.divide(new BigDecimal("365"), 10, ROUND_HALF_UP);

        return BigDecimalUtil.to5Point(income);
    }

    /**
     * 获取待支付提单详情
     *
     * @param accessToken
     * @param orderNO
     * @return
     */
    @GetMapping("/detail")
    public SerializeObject getBill(@RequestHeader String accessToken, String orderNO) {
        /*private int leasebackDays;
        private String leasebackStartTime;
        private String leasebackEndTime;
        private String leasebackActualTime;
        private int leasebackDeductibleDays;
        private BigDecimal leasebackIncomeAmount;
        private int leasebackIncomeType;
        */
        PayTbill payTbill = payTbillService.selectByOrderNO(orderNO);
        SerializeObject<ProductFindBean> productFindBean = productService.queryProductById(payTbill.getProductId());
        if (null == productFindBean || productFindBean.getCode() != ResultType.NORMAL) {
            return new SerializeObjectError("00000005");
        }

        ProductFindBean productBean = productFindBean.getData();
        if (productBean == null || productBean.getLeaseDayList() == null || productBean.getLeaseDayList().size() == 0) {
            return new SerializeObjectError("00000003");
        }
        Integer leaseCalculateGoldType = productBean.getLeaseCalculateGoldType();
        leaseCalculateGoldType = leaseCalculateGoldType == null ? 1 : leaseCalculateGoldType;
        String point = "";
        if (leaseCalculateGoldType == 1) {
            point = "02:30";
        } else {
            point = productBean.getLeaseCalculateGoldTime();
        }
        SimpleDateFormat format = new SimpleDateFormat(NORMAL_DATE_FORMAT);
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, -1);
        String someday = format.format(calendar.getTime()) + " " + point;
        SerializeObject<Double> result = priceService.getSomedayPrice(someday);
        payTbill.setLeasebackPrice(result.getData());
        //查询回租相关信息
        if (payTbill != null && payTbill.getLeaseId() > 0) {
            if (result != null) {
                double price = result.getData();
                List<LeaseDay> leaseDayList = productBean.getLeaseDayList();
                LeaseDay readlLeaseDay = null;
                for (LeaseDay leaseDay : leaseDayList) {
                    if (leaseDay.getId() == payTbill.getLeaseId()) {
                        readlLeaseDay = leaseDay;
                        break;
                    }
                }
                if (readlLeaseDay == null) {
                    return new SerializeObjectError("00000002");
                }
                Integer incomeType = productBean.getLeaseCloseType();
                incomeType = incomeType == null ? 1 : incomeType;
                payTbill.setLeasebackIncomeType(incomeType);
                BigDecimal income = calculateIncomeAmount(new BigDecimal(payTbill.getTotalGram()), readlLeaseDay.getLeaseDay(), readlLeaseDay.getYearsIncome());

                LocalDateTime startTime = UF.getDateTime(UF.getFormatDateNow()).plusDays(productBean.getInterestAccrualDay());
                LocalDateTime endTime = startTime.plusDays(readlLeaseDay.getLeaseDay());
                payTbill.setLeasebackStartTime(UF.getFormatDateTime(UF.getDateTime()));
                payTbill.setLeasebackEndTime(UF.getFormatDateTime(endTime));
                payTbill.setLeasebackDays(readlLeaseDay.getLeaseDay());
                int beans = (int) Math.round(income.multiply(new BigDecimal(GoldBeanProportionEnum.PROPORTION.getValue())).doubleValue());
                payTbill.setLeasebackIncomeBeans(beans);
                //回租奖励（元）
                payTbill.setLeasebackIncomeAmount(BigDecimalUtil.to2Point(income.multiply(new BigDecimal(price))));
                //回租金生金奖励
                payTbill.setLeasebackGoldGiveGoldAmount(payTbill.getLeasebackIncomeAmount());
                if (StringUtils.isNotBlank(payTbill.getTicketId()) && !StringUtils.equals(payTbill.getTicketId(), "0")) {
                    SerializeObject<CouponMemberBean> couponBean = couponRepertoryService.getMemberCoupon(payTbill.getTicketId());
                    if (couponBean == null || couponBean.getData() == null) {
                        return new SerializeObjectError("00000005");
                    }
                    //无减免天数
                    //payTbill.setLeasebackDeductibleDays(couponBean.getData().getDiscountAmount());
                    //回租福利卷 减时卷  当前已不再使用
                    payTbill.setLeasebackActualTime(UF.getFormatDateTime(endTime));
                    //黄金红包奖励
                    payTbill.setLeasebackCouponAwardAmount(BigDecimalUtil.to2Point(new BigDecimal(couponBean.getData().getDiscountAmount()).divide(new BigDecimal(1000)).multiply(new BigDecimal(price))));
                    //回租奖励（元） = 黄金红包奖励 + 回租金生金奖励
                    payTbill.setLeasebackIncomeAmount(payTbill.getLeasebackCouponAwardAmount().add(payTbill.getLeasebackGoldGiveGoldAmount()));
                } else {
                    payTbill.setLeasebackActualTime(UF.getFormatDateTime(endTime));
                    payTbill.setLeasebackDeductibleDays(0);
                }
                BigDecimal discountAmount = BigDecimal.ZERO;
                SerializeObject discountRateBean = rateSettingsService.findONTemplateByType(2);
                int discountAmountType = 1;
                if (discountRateBean != null && discountRateBean.getData() != null) {
                    PrivilegeTemplateBean bean = JSON.parseObject(JSONObject.toJSONString(discountRateBean.getData()), PrivilegeTemplateBean.class);
                    if (bean != null && bean.getWay() != null) {
                        discountAmountType = bean.getWay();
                    }
                    getLog().info("回租奖励模板：" + JSON.toJSONString(bean));
                    discountAmount = fundRateConfig.getDiscountAmount(bean, new BigDecimal(readlLeaseDay.getLeaseDay()), 1);
                    getLog().info("回租奖励数量：" + discountAmount);
                }
                if (discountAmountType == 3) {
                    discountAmount = new BigDecimal(discountAmount.intValue());
                }
                payTbill.setLeasebackDiscountAmount(discountAmount);
                payTbill.setLeasebackDiscountAmountType(discountAmountType);
            }
        }
        return new SerializeObject<>(ResultType.NORMAL, "00000001", payTbill);
    }

    @GetMapping("/sale/detail")
    public SerializeObject getSaleBill(@RequestHeader String accessToken, String orderNO) {
        return new SerializeObject<>(ResultType.NORMAL, "00000001", payTbillSoldService.selectByOrderNO(orderNO));
    }

    @GetMapping("/leaseback/detail")
    public SerializeObject getLeasebackBill(@RequestHeader String accessToken, String orderNO) {
        return new SerializeObject<>(ResultType.NORMAL, "00000001", payTbillLeasebackService.selectByOrderNO(orderNO));
    }

    /**
     * 生成待支付提单
     *
     * @param accessToken
     * @param productId
     * @param num
     * @param beans
     * @param couponId
     * @param leaseId
     * @param ticketId
     * @return
     */
    @PostMapping
    public SerializeObject update(@RequestHeader String accessToken, String productId, int num, Integer beans, String couponId, Integer leaseId, String ticketId) {
        beans = beans == null ? 0 : beans;
        if (StringUtils.isBlank(productId) || num < 1 || beans < 0) {
            return new SerializeObjectError("00000002");
        }
        LoginBean loginBean = LoginHelper.getLoginBean();
        if (loginBean == null || StringUtils.isBlank(loginBean.getAccessToken()) || !StringUtils.equals(accessToken, loginBean.getAccessToken())) {
            return new SerializeObject<>(ResultType.UNLOGIN, "00000102");
        }
        String memberId = LoginHelper.getLoginId();
        leaseId = leaseId == null ? 0 : leaseId;
        ticketId = UF.toString(ticketId);
        if (StringUtils.isBlank(memberId)) {
            return new SerializeObjectError("00000102");
        }

        return new SerializeObject<>(ResultType.NORMAL, "00000001", payTbillService.save(memberId, productId, num, beans, couponId, leaseId, ticketId));
    }

    /**
     * 提单生成记录查询
     *
     * @param accessToken
     * @param page
     * @param order
     * @param mobile
     * @param name
     * @param startGram
     * @param endGram
     * @param startDate
     * @param endDate
     * @param status
     * @param source
     * @param productType 产品类型 6.实物金  7.体验金 8.安稳金 9.折扣金
     * @return
     */
    @GetMapping(value = "/list")
    public SerializeObject<DataTable<PayTbill>> queryForList(@RequestHeader String accessToken, Page page, Order order,
                                                             String mobile, String name, Integer startGram, Integer endGram, String startDate, String endDate,
                                                             Integer status, String source, Integer[] productType,
                                                             String tbillNo, String tbillMoneyMin, String tbillMoneyMax) {
        mobile = UF.toString(mobile);
        name = UF.toString(name);
        startDate = UF.toString(startDate);
        endDate = UF.toString(endDate);
        source = UF.toString(source);
        startGram = startGram == null ? -1 : startGram;
        endGram = endGram == null ? -1 : endGram;
        status = status == null ? -1 : status;
        int total = payTbillService.count(mobile, name, startGram, endGram, startDate, endDate, status, source, productType, tbillNo, tbillMoneyMin, tbillMoneyMax);
        page.setTotal(total);
        if (total > 0) {
            List<PayTbill> list = payTbillService.query(mobile, name, startGram, endGram, startDate, endDate, status, source, order.getOrder(), order.getSort(),
                    PaginationUtil.getOffset(page.getPageNum(), page.getPageSize()), PaginationUtil.getPageSize(page.getPageSize()), productType,
                    tbillNo, tbillMoneyMin, tbillMoneyMax);
            Map<String, Object> parmasMap = new HashMap<>();
            if (list != null) {
                for (PayTbill payTbill : list) {
                    String lockMack = "否";
                    if (StringUtils.isNotBlank(payTbill.getCouponId())) {
                        if (payTbill.getLeasebackTimes() == 0) {
                            LocalDateTime startTime = UF.getDateTime(payTbill.getAddTime());
                            LocalDateTime endTime = LocalDateTime.now();
                            Duration duration = Duration.between(startTime, endTime);
                            long days = duration.toDays();
                            //long hours = duration.toHours();
                            if (days < 30) {
                                lockMack = "是";
                                payTbill.setLockDays(Integer.parseInt(String.valueOf(30 - days)));
                            }
                        }
                    }
                    payTbill.setLockMark(lockMack);
                }
                PayTbillStatistic payTbillStatistic = converListToBean(list);
                parmasMap = Common.beanToMap(payTbillStatistic);
            }
            return new SerializeObject<>(ResultType.NORMAL, new DataOtherTable<PayTbill>(page.getPageNum(), page.getPageSize(), page.getTotal(), list, parmasMap));
        }
        return new SerializeObject<>(ResultType.NORMAL, new DataTable<PayTbill>(page.getPageNum(), page.getPageSize(), page.getTotal(), new ArrayList<PayTbill>()));
    }

    @GetMapping(value = "/export")
    public void queryForExport(HttpServletResponse response, Integer menu, Order order, String mobile, String name, Integer startGram, Integer endGram, String startDate, String endDate, Integer status, String source, Integer[] productType,
                               String tbillNo, String tbillMoneyMin, String tbillMoneyMax) {
        mobile = UF.toString(mobile);
        name = UF.toString(name);
        startDate = UF.toString(startDate);
        endDate = UF.toString(endDate);
        source = UF.toString(source);
        startGram = startGram == null ? -1 : startGram;
        endGram = endGram == null ? -1 : endGram;
        menu = menu == null ? 1 : menu;
        status = status == null ? -1 : status;
        List<PayTbill> list = payTbillService.query(mobile, name, startGram, endGram, startDate, endDate, status, source, order.getOrder(), order.getSort(), 0, 0, productType,
                tbillNo, tbillMoneyMin, tbillMoneyMax);
        if (list == null) {
            list = new ArrayList<PayTbill>();
        }
        String[] columnNames = null;
        String[] columns = null;
        String fileName = null;
        String[] firstLines = null;
        if (menu == 1) {
            fileName = "提单生成记录";
            String[] tpColumnNames = {"序号", "手机号", "用户姓名", "操作流水号", "提单编号", "产品类型", "产品名称", "购买克重（克）", "购买提单金额（元）",
                    "购买金价（元/克）", "金豆抵扣（克）", "使用抵扣券（克）", "抵扣券编号", "实际支付克重（克）", "实际支付金额（元）",
                    "支付状态", "购买时间"};
            String[] tpColumns = {"index", "mobile", "name", "orderNO", "orderNO", "productTypeMark", "productName", "totalGram", "totalAmount", "goldPrice", "beanGram",
                    "couponGram", "couponId", "payGram", "payAmount", "statusMark", "addTime"};
            columnNames = tpColumnNames;
            columns = tpColumns;
            PayTbillStatistic payTbillStatistic = converListToBean(list);
            String[] lines = {"合计", payTbillStatistic.getCountPersonNum() + "人", payTbillStatistic.getCountPersonNum() + "人", "/", payTbillStatistic.getCountNum() + "笔", "/", "/"
                    , payTbillStatistic.getTotalGram() + "克", payTbillStatistic.getTotalAmount() + "元", "/", payTbillStatistic.getTotalBeanGram() + "克", payTbillStatistic.getTotalCouponGram() + "克"
                    , "/", payTbillStatistic.getTotalPayGram() + "克", payTbillStatistic.getTotalPayAmount() + "元", "全部", "/"};
            firstLines = lines;
        } else if (menu == 2) {
            fileName = "提单状态记录表";
            String[] tpColumnNames = {"序号", "手机号", "用户姓名", "提单编号", "产品类型", "提单克重", "提单生成时间", "当前提单状态", "最新状态变更时间"};
            String[] tpColumns = {"index", "mobile", "name", "orderNO", "productTypeMark", "totalGram", "addTime", "statusMark", "modifyTime"};
            columnNames = tpColumnNames;
            columns = tpColumns;
        } else if (menu == 3) {
            fileName = "待处理提单记录表";
            String[] tpColumnNames = {"序号", "手机号", "用户姓名", "待处理提单生成时间", "待处理提单编号", "产品类型", "待处理提单克重（克）", "待处理提单来源",
                    "是否使用黄金抵扣券", "是否处于出售锁定期", "出售锁定期时长（天）"};
            String[] tpColumns = {"index", "mobile", "name", "addTime", "orderNO", "productTypeMark", "totalGram", "source", "statusMark", "statusMark", "lockDays"};
            columnNames = tpColumnNames;
            columns = tpColumns;
        }
        int index = 1;
        for (PayTbill bean : list) {
            bean.setIndex(index);
            index++;
            if (menu == 1) {
                if (bean.getStatus() == 0) {
                    bean.setStatusMark(TbillStatusEnum.WAIT_FOR_PAYING.getRemark());
                } else if (bean.getStatus() == 1) {
                    bean.setStatusMark(TbillStatusEnum.PAST.getRemark());
                } else if (bean.getStatus() == 7) {
                    bean.setStatusMark("已失败");
                } else {
                    bean.setStatusMark("已支付");
                }
            } else if (menu == 2) {
                bean.setStatusMark(TbillStatusEnum.getRemartByStatus(bean.getStatus()));
            } else {
                bean.setStatusMark("无");
            }
            String lockMack = "否";
            if (StringUtils.isNotBlank(bean.getCouponId())) {
                if (bean.getLeasebackTimes() == 0) {
                    LocalDateTime startTime = UF.getDateTime(bean.getAddTime());
                    LocalDateTime endTime = LocalDateTime.now();
                    Duration duration = Duration.between(startTime, endTime);
                    long days = duration.toDays();
                    //long hours = duration.toHours();
                    if (days < 30) {
                        lockMack = "是";
                        bean.setLockDays(Integer.parseInt(String.valueOf(30 - days)));
                    }
                }
            }
            bean.setLockMark(lockMack);
            if (bean.getProductType() != null) {
                bean.setProductTypeMark(ProductTypeEnum.getByCode(bean.getProductType()));
            }
        }
        ExportExcelController<PayTbill> export = new ExportExcelController<PayTbill>();
        if (menu == 1) {
            export.exportUnlikeExcel(fileName, fileName, columnNames, columns, list, response, ExportExcelUtil.EXCEL_FILE_2003, firstLines);
        } else {
            export.exportExcel(fileName, fileName, columnNames, columns, list, response, ExportExcelUtil.EXCEL_FILE_2003);
        }
    }

    @GetMapping(value = "/status/list")
    public SerializeObject<DataTable<PayTbillStatus>> queryForList(@RequestHeader String accessToken, Page page, Order order, String tbillNO, String type, Integer status) {
        tbillNO = UF.toString(tbillNO);
        type = UF.toString(type);
        status = status == null ? -1 : status;
        int total = payTbillStatusService.count(tbillNO, type, status);
        page.setTotal(total);
        if (total > 0) {
            List<PayTbillStatus> list = payTbillStatusService.query(tbillNO, type, status, order.getOrder(), order.getSort(),
                    PaginationUtil.getOffset(page.getPageNum(), page.getPageSize()), PaginationUtil.getPageSize(page.getPageSize()));
            return new SerializeObject<>(ResultType.NORMAL, new DataTable<PayTbillStatus>(page.getPageNum(), page.getPageSize(), page.getTotal(), list));
        }
        return new SerializeObject<>(ResultType.NORMAL, new DataTable<PayTbillStatus>(page.getPageNum(), page.getPageSize(), page.getTotal(), new ArrayList<PayTbillStatus>()));
    }

    @GetMapping(value = "/status/export")
    public void queryForExport(HttpServletResponse response, Order order, String tbillNO, String type, Integer status) {
        tbillNO = UF.toString(tbillNO);
        type = UF.toString(type);
        status = status == null ? -1 : status;
        List<PayTbillStatus> list = payTbillStatusService.query(tbillNO, type, status, order.getOrder(), order.getSort(), 0, 0);
        if (list == null) {
            list = new ArrayList<PayTbillStatus>();
        }
        String fileName = "提单状态变更详情";
        String[] columnNames = {"序号", "操作流水号", "操作类型", "操作时间", "提单变更状态", "状态变更时间", "状态备注"};
        String[] columns = {"index", "orderNO", "type", "addTime", "statusMark", "modifyTime", "remark"};
        int index = 1;
        for (PayTbillStatus bean : list) {
            bean.setIndex(index);
            index++;
            bean.setStatusMark(TbillStatusEnum.getRemartByStatus(bean.getStatus()));
        }
        ExportExcelController<PayTbillStatus> export = new ExportExcelController<PayTbillStatus>();
        export.exportExcel(fileName, fileName, columnNames, columns, list, response, ExportExcelUtil.EXCEL_FILE_2003);
    }

    /**
     * 回租中提单记录表,提单历史回租纪录,已到期提单记录表列表
     *
     * @param accessToken
     * @param page
     * @param order
     * @param mobile
     * @param name
     * @param startGram
     * @param endGram
     * @param startOfStartDate
     * @param endOfStartDate
     * @param startOfEndDate
     * @param endOfEndDate
     * @param status
     * @param tbillNO
     * @param leasebackDays
     * @param productType
     * @return
     */
    @GetMapping(value = "/leaseback/list")
    public SerializeObject<DataTable<PayTbillLeaseback>> queryForList(@RequestHeader String accessToken, Page page, Order order, String mobile, String name, Integer startGram, Integer endGram, String startOfStartDate,
                                                                      String endOfStartDate, String startOfEndDate, String endOfEndDate, Integer status, String tbillNO, Integer[] leasebackDays,
                                                                      Integer[] productType, String tbillMoneyMin, String tbillMoneyMax) {

        mobile = UF.toString(mobile);
        name = UF.toString(name);
        startGram = startGram == null ? -1 : startGram;
        endGram = endGram == null ? -1 : endGram;
        startOfStartDate = UF.toString(startOfStartDate);
        endOfStartDate = UF.toString(endOfStartDate);
        startOfEndDate = UF.toString(startOfEndDate);
        endOfEndDate = UF.toString(endOfEndDate);
        tbillNO = UF.toString(tbillNO);
        status = status == null ? 0 : status;
        //leasebackDays = leasebackDays == null ? -1 : leasebackDays;
        if (StringUtils.isNotBlank(tbillNO)) {
            status = 1;
        }
        int total = payTbillLeasebackService.count(mobile, name, startGram, endGram, startOfStartDate, endOfStartDate, startOfEndDate, endOfEndDate, status, tbillNO, leasebackDays, productType,
                tbillMoneyMin, tbillMoneyMax);
        page.setTotal(total);
        if (total > 0) {
            List<PayTbillLeaseback> list = payTbillLeasebackService.query(mobile, name, startGram, endGram, startOfStartDate, endOfStartDate, startOfEndDate, endOfEndDate, status, tbillNO, leasebackDays, order.getOrder(), order.getSort(),
                    PaginationUtil.getOffset(page.getPageNum(), page.getPageSize()), PaginationUtil.getPageSize(page.getPageSize()), productType,
                    tbillMoneyMin, tbillMoneyMax);
            PayTbillLeasebackStatistic payTbillLeasebackStatistic = converLeasebackListToBean(list);
            Map<String, Object> parmasMap = Common.beanToMap(payTbillLeasebackStatistic);
            return new SerializeObject<>(ResultType.NORMAL, new DataOtherTable<PayTbillLeaseback>(page.getPageNum(), page.getPageSize(), page.getTotal(), list, parmasMap));
        }
        return new SerializeObject<>(ResultType.NORMAL, new DataTable<PayTbillLeaseback>(page.getPageNum(), page.getPageSize(), page.getTotal(), new ArrayList<PayTbillLeaseback>()));
    }

    @GetMapping(value = "/leaseback/export")
    public void queryForExport(HttpServletResponse response, Order order, String mobile, String name, Integer startGram, Integer endGram, String startOfStartDate,
                               String endOfStartDate, String startOfEndDate, String endOfEndDate, Integer status, String tbillNO, Integer[] leasebackDays, Integer[] productType
            , String tbillMoneyMin, String tbillMoneyMax) {
        mobile = UF.toString(mobile);
        name = UF.toString(name);
        startGram = startGram == null ? -1 : startGram;
        endGram = endGram == null ? -1 : endGram;
        startOfStartDate = UF.toString(startOfStartDate);
        endOfStartDate = UF.toString(endOfStartDate);
        startOfEndDate = UF.toString(startOfEndDate);
        endOfEndDate = UF.toString(endOfEndDate);
        tbillNO = UF.toString(tbillNO);
        status = status == null ? 0 : status;
        //leasebackDays = leasebackDays == null ? -1 : leasebackDays;
        if (StringUtils.isNotBlank(tbillNO)) {
            status = 1;
        }
        List<PayTbillLeaseback> list = payTbillLeasebackService.query(mobile, name, startGram, endGram, startOfStartDate, endOfStartDate, startOfEndDate, endOfEndDate, status, tbillNO, leasebackDays, order.getOrder(), order.getSort(), 0, 0, productType
                , tbillMoneyMin, tbillMoneyMax);
        if (list == null) {
            list = new ArrayList<PayTbillLeaseback>();
        }

        String[] columnNames = null;
        String[] columns = null;
        String fileName = null;
        String[] firstLines = null;
        if (StringUtils.isNotBlank(tbillNO)) {
            fileName = "提单历史回租纪录";
            String[] tpColumnNames = {"序号", "流水号", "回租开始时间", "回租到期时间", "回租期限", "回租时价格（元/克）", "年化收益（%）",
                    "回租金生金奖励（元）", "对应金豆（个）", "使用黄金红包编号", "黄金红包额度（mg）", "对应加息年化（%）", "黄金红包奖励（元）", "回租专享优惠（元）", "回租总奖励（元）", "奖励到账时间"};
            String[] tpColumns = {"index", "orderNO", "startTime", "endTime", "leasebackDays", "goldPrice", "yearIncome", "goldGiveGoldAmount", "incomeBeans",
                    "couponId", "couponDiscountAmount", "couponYearIncome", "couponAwardAmount", "discountAmount", "incomeAmount", "grantTime"};
            columnNames = tpColumnNames;
            columns = tpColumns;
        } else if (status == 0) {
            fileName = "回租中提单记录表";
            String[] tpColumnNames = {"序号", "手机号", "用户姓名", "当前回租操作流水号", "回租中提单编号", "产品类型", "提单历史回租纪录", "回租中提单克重（克）", "回租中提单金额", "回租期限", "回租时价格（元/克）", "年化收益（%）",
                    "回租开始时间", "回租到期时间", "回租金生金奖励(元)", "对应金豆（个）", "使用黄金红包编号", "黄金红包名称", "黄金红包额度（mg）", "对应加息年化（%）", "黄金红包奖励（元）", "回租专享优惠（元）", "回租总奖励（元）",
                    "奖励到账时间",};
            String[] tpColumns = {"index", "mobile", "name", "orderNO", "tbillNO", "productTypeMark", "leasebackTimes", "totalGram", "totalMoney", "leasebackDays", "goldPrice", "yearIncome", "startTime", "endTime",
                    "goldGiveGoldAmount", "incomeBeans", "couponId", "couponName", "couponDiscountAmount", "couponYearIncome", "couponAwardAmount", "discountAmount", "incomeAmount", "grantTime"};
            columnNames = tpColumnNames;
            columns = tpColumns;
            PayTbillLeasebackStatistic payTbillLeasebackStatistic = converLeasebackListToBean(list);
            String[] lines = {"合计", payTbillLeasebackStatistic.getCountPersonNum() + "人", payTbillLeasebackStatistic.getCountPersonNum() + "人", "全部", payTbillLeasebackStatistic.getCountNum() + "笔", "/", "/"
                    , payTbillLeasebackStatistic.getTotalGram() + "克", payTbillLeasebackStatistic.getTotalAmount() + "元", "/", "/", "/", "/", "/", payTbillLeasebackStatistic.getTotalGoldGiveGoldAmount() + "元", payTbillLeasebackStatistic.getTotalBean() + "个"
                    , "/", "/", payTbillLeasebackStatistic.getTotalCouponAmount() + "mg", "", payTbillLeasebackStatistic.getTotalCouponAwardAmount() + "元", payTbillLeasebackStatistic.getTotalDiscountAmount() + "元", payTbillLeasebackStatistic.getTotalIncomeAmount() + "元", "/"};
            firstLines = lines;

        } else if (status == 1) {
            fileName = "已到期提单记录表";
            String[] tpColumnNames = {"序号", "手机号", "用户姓名", "提单编号", "产品类型", "已到期提单克重（克）", "已到期提单金额（元）", "回租开始时间", "回租到期时间", "回租期限", "回租时价格（元/克）", "年化收益（%）",
                    "回租金生金奖励（元）", "对应金豆（个）", "使用黄金红包编号", "黄金红包额度（mg）", "对应加息年化（%）", "黄金红包奖励（元）", "回租专享优惠（元）", "回租总奖励（元）", "奖励到账时间"};
            String[] tpColumns = {"index", "mobile", "name", "tbillNO", "productTypeMark", "totalGram", "totalMoney", "startTime", "endTime", "leasebackDays", "goldPrice", "yearIncome", "goldGiveGoldAmount", "incomeBeans",
                    "couponId", "couponDiscountAmount", "couponYearIncome", "couponAwardAmount", "discountAmount", "incomeAmount", "grantTime"};
            columnNames = tpColumnNames;
            columns = tpColumns;
            PayTbillLeasebackStatistic payTbillLeasebackStatistic = converLeasebackListToBean(list);
            String[] lines = {"合计", payTbillLeasebackStatistic.getCountPersonNum() + "人", payTbillLeasebackStatistic.getCountPersonNum() + "人", payTbillLeasebackStatistic.getCountNum() + "笔", "/"
                    , payTbillLeasebackStatistic.getTotalGram() + "克", payTbillLeasebackStatistic.getTotalAmount() + "元", "/", "/", "/", "/", "/", payTbillLeasebackStatistic.getTotalGoldGiveGoldAmount() + "元", payTbillLeasebackStatistic.getTotalBean() + "个"
                    , "/", payTbillLeasebackStatistic.getTotalCouponAmount() + "mg", "/", payTbillLeasebackStatistic.getTotalCouponAwardAmount() + "元", payTbillLeasebackStatistic.getTotalDiscountAmount() + "元", payTbillLeasebackStatistic.getTotalIncomeAmount() + "元", "/"};
            firstLines = lines;
        }
        int index = 1;
        for (PayTbillLeaseback bean : list) {
            bean.setIndex(index);
            index++;
            bean.setAmountMark(String.valueOf(bean.getIncomeAmount()));
            bean.setBeansMark(String.valueOf(bean.getIncomeBeans()));
            if (bean.getProductType() != null) {
                bean.setProductTypeMark(ProductTypeEnum.getByCode(bean.getProductType()));
            }
        }
        ExportExcelController<PayTbillLeaseback> export = new ExportExcelController<PayTbillLeaseback>();
        if (status == 0 || status == 1) {
            export.exportUnlikeExcel(fileName, fileName, columnNames, columns, list, response, ExportExcelUtil.EXCEL_FILE_2003, firstLines);
        } else {
            export.exportExcel(fileName, fileName, columnNames, columns, list, response, ExportExcelUtil.EXCEL_FILE_2003);
        }

    }

    /**
     * 已出售提单记录
     *
     * @param accessToken
     * @param page
     * @param order
     * @param mobile
     * @param name
     * @param startGram
     * @param endGram
     * @param startDate
     * @param endDate
     * @param productType
     * @return
     */
    @GetMapping(value = "/sold/list")
    public SerializeObject<DataTable<PayTbillSold>> queryForList(@RequestHeader String accessToken, Page page, Order order, String mobile, String name, Integer startGram,
                                                                 Integer endGram, String startDate, String endDate, Integer[] productType,
                                                                 String tbillNO, String totalAmountMin, String totalAmountMax, String actualAmountMin, String actualAmountMax) {
        mobile = UF.toString(mobile);
        name = UF.toString(name);
        startGram = startGram == null ? -1 : startGram;
        endGram = endGram == null ? -1 : endGram;
        startDate = UF.toString(startDate);
        endDate = UF.toString(endDate);
        int total = payTbillSoldService.count(mobile, name, startGram, endGram, startDate, endDate, productType,
                tbillNO, totalAmountMin, totalAmountMax, actualAmountMin, actualAmountMax);
        page.setTotal(total);
        if (total > 0) {
            List<PayTbillSold> list = payTbillSoldService.query(mobile, name, startGram, endGram, startDate, endDate, order.getOrder(), order.getSort(),
                    PaginationUtil.getOffset(page.getPageNum(), page.getPageSize()), PaginationUtil.getPageSize(page.getPageSize()), productType,
                    tbillNO, totalAmountMin, totalAmountMax, actualAmountMin, actualAmountMax);

            PayTbillSoldStatistic payTbillSoldStatistic = converSoldListToBean(list);
            Map<String, Object> parmasMap = Common.beanToMap(payTbillSoldStatistic);
            return new SerializeObject<>(ResultType.NORMAL, new DataOtherTable<PayTbillSold>(page.getPageNum(), page.getPageSize(), page.getTotal(), list, parmasMap));
        }
        return new SerializeObject<>(ResultType.NORMAL, new DataTable<PayTbillSold>(page.getPageNum(), page.getPageSize(), page.getTotal(), new ArrayList<PayTbillSold>()));
    }

    @GetMapping(value = "/sold/export")
    public void queryForExport(HttpServletResponse response, Order order, String mobile, String name, Integer startGram, Integer endGram, String startDate, String endDate, Integer[] productType,
                               String tbillNO, String totalAmountMin, String totalAmountMax, String actualAmountMin, String actualAmountMax) {
        mobile = UF.toString(mobile);
        name = UF.toString(name);
        startGram = startGram == null ? -1 : startGram;
        endGram = endGram == null ? -1 : endGram;
        startDate = UF.toString(startDate);
        endDate = UF.toString(endDate);
        List<PayTbillSold> list = payTbillSoldService.query(mobile, name, startGram, endGram, startDate, endDate, order.getOrder(), order.getSort(), 0, 0, productType,
                tbillNO, totalAmountMin, totalAmountMax, actualAmountMin, actualAmountMax);
        if (list == null) {
            list = new ArrayList<PayTbillSold>();
        }
        String fileName = "已出售提单记录表";
        String[] columnNames = {"序号", "手机号", "姓名", "操作流水号", "已出售提单编号", "产品类型", "已出售提单克重（克）", "出售时金价（元/克）", "出售时间", "是否使用抵扣券",
                "出售手续费（元）", "扣减已优惠金额（元）", "出售到账金额（元）", "出售金额到账时间"};
        String[] columns = {"index", "mobile", "name", "orderNO", "tbillNO", "productTypeMark", "totalGram", "goldPrice", "addTime", "couponId", "fee", "couponAmount", "actualAmount", "successTime"};

        PayTbillSoldStatistic payTbillSoldStatistic = converSoldListToBean(list);
        String[] firstLines = {"合计", payTbillSoldStatistic.getCountPersonNum() + "人", payTbillSoldStatistic.getCountPersonNum() + "人", "/"
                , payTbillSoldStatistic.getCountNum() + "笔", "/", payTbillSoldStatistic.getTotalGram() + "克", "/", "/", "/", payTbillSoldStatistic.getTotalFee() + "元"
                , payTbillSoldStatistic.getTotalCouponAmount() + "元", payTbillSoldStatistic.getTotalActualAmount() + "元", "/"};
        int index = 1;
        for (PayTbillSold bean : list) {
            bean.setIndex(index);
            index++;
            if (StringUtils.isNotBlank(bean.getCouponId())) {
                bean.setCouponId("是");
            } else {
                bean.setCouponId("否");
            }
            if (bean.getProductType() != null) {
                bean.setProductTypeMark(ProductTypeEnum.getByCode(bean.getProductType()));
            }
        }
        ExportExcelController<PayTbillSold> export = new ExportExcelController<PayTbillSold>();
        //export.exportExcel(fileName, fileName, columnNames, columns, list, response, ExportExcelUtil.EXCEL_FILE_2003);
        export.exportUnlikeExcel(fileName, fileName, columnNames, columns, list, response, ExportExcelUtil.EXCEL_FILE_2003, firstLines);
    }

    /**
     * 提单涨幅收益表
     * @param accessToken
     * @param page
     * @param order
     * @param mobile
     * @param name
     * @param startGram
     * @param endGram
     * @param startDate
     * @param endDate
     * @param productType
     * @param tbillNO
     * @param buyTotalAmountMin
     * @param buyTotalAmountMax
     * @param soldTotalAmountMin
     * @param soldTotalAmountMax
     * @return
     */
    @GetMapping(value = "/sold/incomeList")
    public SerializeObject<DataTable<PayTbillSold>> queryIncomeList(@RequestHeader String accessToken, Page page, Order order, String mobile, String name, Integer startGram,
                                                                 Integer endGram, String startDate, String endDate, Integer[] productType, String tbillNO, String buyTotalAmountMin, String buyTotalAmountMax, String soldTotalAmountMin, String soldTotalAmountMax) {
        mobile = UF.toString(mobile);
        name = UF.toString(name);
        startGram = startGram == null ? -1 : startGram;
        endGram = endGram == null ? -1 : endGram;
        startDate = UF.toString(startDate);
        endDate = UF.toString(endDate);
        //PaginationUtil.getOffset(page.getPageNum(), page.getPageSize()), PaginationUtil.getPageSize(page.getPageSize()),

        if (StringUtils.isNotBlank(order.getOrder()) && order.getOrder().contains(",")){
            order.setOrder(order.getOrder().replaceAll(",",""));
            order.setSort(order.getSort().replaceAll(",",""));
        }

        List<PayTbillSold> list = payTbillSoldService.queryIncome(mobile, name, startGram, endGram, startDate, endDate, order.getOrder(), order.getSort(), productType,
                tbillNO, buyTotalAmountMin, buyTotalAmountMax, soldTotalAmountMin, soldTotalAmountMax);


        if (page.getPageSize() <= 0) {
            page.setPageSize(config.getPageSize());
        }
        page.setTotal(0);

        if (list != null && list.size() > 0) {
            page.setTotal(list.size());

            int index = 1;
            for (PayTbillSold bean : list) {
                bean.setIndex(index);
                index++;
                if (bean.getProductType() != null) {
                    bean.setProductTypeMark(ProductTypeEnum.getByCode(bean.getProductType()));
                }
            }

            Map<String, Object> parmasMap = converSoldIncomeListToMap(list);

            if (page.getPageSize() > 0) {
                list = list.stream().skip((PaginationUtil.getPage(page.getPageNum()) - 1) * page.getPageSize()).limit(page.getPageSize()).collect(Collectors.toList());
            }

            return new SerializeObject<>(ResultType.NORMAL, new DataOtherTable<PayTbillSold>(page.getPageNum(), page.getPageSize(), page.getTotal(), list, parmasMap));
        }
        return new SerializeObject<>(ResultType.NORMAL, new DataTable<PayTbillSold>(page.getPageNum(), page.getPageSize(), page.getTotal(), new ArrayList<PayTbillSold>()));
    }

    @GetMapping(value = "/sold/incomeExport")
    public void queryincomeExport(HttpServletResponse response, Order order, String mobile, String name, Integer startGram, Integer endGram, String startDate, String endDate, Integer[] productType,
                               String tbillNO, String buyTotalAmountMin, String buyTotalAmountMax, String soldTotalAmountMin, String soldTotalAmountMax) {
        mobile = UF.toString(mobile);
        name = UF.toString(name);
        startGram = startGram == null ? -1 : startGram;
        endGram = endGram == null ? -1 : endGram;
        startDate = UF.toString(startDate);
        endDate = UF.toString(endDate);

        if (StringUtils.isNotBlank(order.getOrder()) && order.getOrder().contains(",")){
            order.setOrder(order.getOrder().replaceAll(",",""));
            order.setSort(order.getSort().replaceAll(",",""));
        }

        List<PayTbillSold> list = payTbillSoldService.queryIncome(mobile, name, startGram, endGram, startDate, endDate, order.getOrder(), order.getSort(), productType,
                tbillNO, buyTotalAmountMin, buyTotalAmountMax, soldTotalAmountMin, soldTotalAmountMax);


        if (list == null) {
            list = new ArrayList<PayTbillSold>();
        }
        String fileName = "提单涨幅收益表";
        String[] columnNames = {"序号", "手机号", "用户姓名", "已出售提单编号", "产品类型", "提单克重（克）", "购买时提单金额（元）", "出售时提单金额（元）", "出售赚取差价（元）",
                "购买时金价（元/克）", "出售时金价（元/克）", "提单出售时间"};
        String[] columns = {"index", "mobile", "name", "tbillNO", "productTypeMark", "totalGram", "buyTotalAmount", "totalAmount", "incomeAmount",
                "buyGoldPrice", "goldPrice", "addTime"};
        Integer countPersonNum = 0;
        Integer countNum = 0;
        Integer totalGram = 0;
        BigDecimal buyTotalAmount = BigDecimal.ZERO;
        BigDecimal totalAmount = BigDecimal.ZERO;
        BigDecimal incomeAmount = BigDecimal.ZERO;
        if (!CollectionUtils.isEmpty(list)) {
            Map<String, Object> parmasMap = converSoldIncomeListToMap(list);
            countPersonNum = (Integer) parmasMap.get("countPersonNum");
            countNum = (Integer) parmasMap.get("countNum");
            totalGram = (Integer) parmasMap.get("totalGram");
            buyTotalAmount = (BigDecimal) parmasMap.get("buyTotalAmount");
            totalAmount = (BigDecimal)parmasMap.get("totalAmount");
            incomeAmount = (BigDecimal)parmasMap.get("incomeAmount");
        }

        String[] firstLines = {"合计", countPersonNum + "人", countPersonNum + "人",
                countNum + "笔", "全部", totalGram + "克", buyTotalAmount + "元"
                , totalAmount + "元", incomeAmount + "元", "/", "/", "/"};
        int index = 1;
        for (PayTbillSold bean : list) {
            bean.setIndex(index);
            index++;
            if (bean.getProductType() != null) {
                bean.setProductTypeMark(ProductTypeEnum.getByCode(bean.getProductType()));
            }
        }
        ExportExcelController<PayTbillSold> export = new ExportExcelController<PayTbillSold>();
        //export.exportExcel(fileName, fileName, columnNames, columns, list, response, ExportExcelUtil.EXCEL_FILE_2003);
        export.exportUnlikeExcel(fileName, fileName, columnNames, columns, list, response, ExportExcelUtil.EXCEL_FILE_2003, firstLines);
    }

    /**
     * 提单复投记录表
     * @param accessToken
     * @param page
     * @param order
     * @param mobile
     * @param name
     * @param tbillNO
     * @param startGram
     * @param endGram
     * @param startAmount
     * @param endAmount
     * @param s_startTime
     * @param e_startTime
     * @param s_endTime
     * @param e_endTime
     * @param leasebackDays
     * @param productIds
     * @return
     */
    @GetMapping(value = "/leaseback/again")
    public SerializeObject<DataTable<PayTbillAgainLeaseback>> queryAgainLeaseback(@RequestHeader String accessToken, Page page, Order order, String mobile, String name, String tbillNo,
                                                                        Integer startGram, Integer endGram, String startAmount, String endAmount, String s_startTime, String e_startTime,
                                                                        String s_endTime, String e_endTime, Integer[] leasebackDays,Integer[] productType) {

        mobile = UF.toString(mobile);
        name = UF.toString(name);
        startGram = startGram == null ? -1 : startGram;
        endGram = endGram == null ? -1 : endGram;
        startAmount = UF.toString(startAmount);
        endAmount = UF.toString(endAmount);
        s_startTime = UF.toString(s_startTime);
        e_startTime = UF.toString(e_startTime);
        s_endTime = UF.toString(s_endTime);
        e_endTime = UF.toString(e_endTime);


        if (page.getPageSize() <= 0) {
            page.setPageSize(config.getPageSize());
        }

        if (StringUtils.isNotBlank(order.getOrder()) && order.getOrder().contains(",")){
            order.setOrder(order.getOrder().replaceAll(",",""));
            order.setSort(order.getSort().replaceAll(",",""));
        }

        List<PayTbillAgainLeaseback> list = payTbillLeasebackService.queryUserAgainLeasebackList(mobile,name,tbillNo,startGram,endGram,startAmount,endAmount,
                s_startTime,e_startTime,s_endTime,e_endTime,leasebackDays,productType,order.getOrder(),order.getSort());
        page.setTotal(0);
        if (list != null && list.size() > 0) {
            page.setTotal(list.size());
            int index = 1;
            for (PayTbillAgainLeaseback bean : list) {
                bean.setTotalAmount(bean.getTotalAmount() == null ? BigDecimal.ZERO : bean.getTotalAmount().setScale(2, BigDecimal.ROUND_HALF_UP));
                bean.setIndex(index);
                index++;
            }

            Map<String, Object> parmasMap = converAgainLeasebackToMap(list);
            if (page.getPageSize() > 0) {
                list = list.stream().skip((PaginationUtil.getPage(page.getPageNum()) - 1) * page.getPageSize()).limit(page.getPageSize()).collect(Collectors.toList());
            }

            return new SerializeObject<>(ResultType.NORMAL, new DataOtherTable<PayTbillAgainLeaseback>(page.getPageNum(), page.getPageSize(), page.getTotal(), list, parmasMap));
        }
        return new SerializeObject<>(ResultType.NORMAL, new DataTable<PayTbillAgainLeaseback>(page.getPageNum(), page.getPageSize(), page.getTotal(), new ArrayList<PayTbillAgainLeaseback>()));
    }

    @GetMapping(value = "/leaseback/againExport")
    public void queryAgainLeasebackExport(HttpServletResponse response, Order order, String mobile, String name, String tbillNo,
                                          Integer startGram, Integer endGram, String startAmount, String endAmount, String s_startTime, String e_startTime,
                                          String s_endTime, String e_endTime, Integer[] leasebackDays,Integer[] productType) {
        mobile = UF.toString(mobile);
        name = UF.toString(name);
        startGram = startGram == null ? -1 : startGram;
        endGram = endGram == null ? -1 : endGram;
        s_startTime = UF.toString(s_startTime);
        e_startTime = UF.toString(e_startTime);
        s_endTime = UF.toString(s_endTime);
        e_endTime = UF.toString(e_endTime);

        if (StringUtils.isNotBlank(order.getOrder()) && order.getOrder().contains(",")){
            order.setOrder(order.getOrder().replaceAll(",",""));
            order.setSort(order.getSort().replaceAll(",",""));
        }

        List<PayTbillAgainLeaseback> list = payTbillLeasebackService.queryUserAgainLeasebackList(mobile,name,tbillNo,startGram,endGram,startAmount,endAmount,
                s_startTime,e_startTime,s_endTime,e_endTime,leasebackDays,productType,order.getOrder(),order.getSort());
        if (list == null) {
            list = new ArrayList<PayTbillAgainLeaseback>();
        }
        String fileName = "提单复投记录表";
        String[] columnNames = {"序号", "复投提单编号", "操作流水号", "手机号", "用户姓名", "复投产品类型", "复投克重（克）", "复投提单金额（元）", "复投时金价（元/克）", "复投提单期限（天）",
                "复投开始时间", "复投到期时间"};
        String[] columns = {"index", "tbillNo", "orderNo", "mobile", "name", "productName", "totalGram", "totalAmount", "goldPrice",
                "leasebackDays", "startTime", "endTime"};
        Integer tbillNoCount = 0;
        Integer orderNoCount = 0;
        Integer nameCount = 0;
        Integer mobileCount = 0;
        Integer totalGram = 0;
        BigDecimal totalAmount = BigDecimal.ZERO;
        if (!CollectionUtils.isEmpty(list)) {
            Map<String, Object> parmasMap = converAgainLeasebackToMap(list);

            tbillNoCount = (Integer) parmasMap.get("tbillNoCount");
            orderNoCount = (Integer) parmasMap.get("orderNoCount");
            nameCount = (Integer) parmasMap.get("nameCount");
            mobileCount = (Integer) parmasMap.get("mobileCount");
            totalGram = (Integer) parmasMap.get("totalGram");
            totalAmount = (BigDecimal)parmasMap.get("totalAmount");
        }

        String[] firstLines = {"合计", tbillNoCount + "笔", orderNoCount + "次",
                mobileCount + "人",  nameCount + "人", "全部", totalGram + "克", totalAmount + "元"
                ,"/","/", "/", "/"};
        int index = 1;
        for (PayTbillAgainLeaseback bean : list) {
            bean.setIndex(index);
            index++;
        }
        ExportExcelController<PayTbillAgainLeaseback> export = new ExportExcelController<PayTbillAgainLeaseback>();
        //export.exportExcel(fileName, fileName, columnNames, columns, list, response, ExportExcelUtil.EXCEL_FILE_2003);
        export.exportUnlikeExcel(fileName, fileName, columnNames, columns, list, response, ExportExcelUtil.EXCEL_FILE_2003, firstLines);
    }

    @GetMapping(value = "/leaseback/history/list")
    public SerializeObject<DataTable<PayTbillLeaseback>> queryForHistoryList(@RequestHeader String accessToken, Page page, String orderNO) {
        if (StringUtils.isNotBlank(orderNO)) {
            int total = payTbillLeasebackService.count("", "", -1, -1, "", "", "", "", 1, orderNO, null, null, null, null);
            page.setTotal(total);
            if (total > 0) {
                List<PayTbillLeaseback> list = payTbillLeasebackService.query("", "", -1, -1, "", "", "", "", 1, orderNO, null, "", "",
                        PaginationUtil.getOffset(page.getPageNum(), page.getPageSize()), PaginationUtil.getPageSize(page.getPageSize()), null, null, null);
                return new SerializeObject<>(ResultType.NORMAL, new DataTable<PayTbillLeaseback>(page.getPageNum(), page.getPageSize(), page.getTotal(), list));
            }
        }
        return new SerializeObject<>(ResultType.NORMAL, new DataTable<PayTbillLeaseback>(page.getPageNum(), page.getPageSize(), page.getTotal(), new ArrayList<PayTbillLeaseback>()));
    }

    /**
     * 提单回租足迹（app）
     *
     * @param accessToken
     * @param orderNO
     * @return
     */
    @GetMapping(value = "/track")
    public SerializeObject<JSONObject> queryForHistoryList(@RequestHeader String accessToken, String orderNO) {
        JSONObject result = new JSONObject();
        if (StringUtils.isNotBlank(orderNO)) {
            result.put("tbillBean", payTbillService.selectByOrderNO(orderNO));
            result.put("leasebackBean", payTbillLeasebackService.query("", "", -1, -1, "", "", "", "", -1, orderNO, null, "", "",
                    0, 0, null, null, null));
            result.put("soldBean", payTbillSoldService.selectByTbillNO(orderNO));
            result.put("extractionBean", extractionGoldService.selectByTbillNO(orderNO));
            return new SerializeObject<>(ResultType.NORMAL, result);
        }
        return new SerializeObject<>(ResultType.NORMAL, result);
    }

    @GetMapping(value = "/frozen/list")
    public SerializeObject<DataTable<FrozenTbillBean>> queryForFrozenList(@RequestHeader String accessToken, Page page, Order order, String mobile, String name, Integer startGram, Integer endGram,
                                                                          String startDate, String endDate) {
        mobile = UF.toString(mobile);
        name = UF.toString(name);
        startDate = UF.toString(startDate);
        endDate = UF.toString(endDate);
        startGram = startGram == null ? -1 : startGram;
        endGram = endGram == null ? -1 : endGram;
        int total = payTbillService.countForFrozenTbills(mobile, name, startGram, endGram, startDate, endDate);
        page.setTotal(total);
        if (total > 0) {
            List<FrozenTbillBean> list = payTbillService.queryForFrozenTbills(mobile, name, startGram, endGram, startDate, endDate, order.getOrder(), order.getSort(),
                    PaginationUtil.getOffset(page.getPageNum(), page.getPageSize()), PaginationUtil.getPageSize(page.getPageSize()));
            if (list != null && list.size() > 0) {
                for (FrozenTbillBean frozenTbillBean : list) {
                    frozenTbillBean.setType("冻结");
                    frozenTbillBean.setRemark(TbillStatusRemark.GOLD_EXTRACTION_PREBOOK.getValue());
                }
            }
            return new SerializeObject<>(ResultType.NORMAL, new DataTable<FrozenTbillBean>(page.getPageNum(), page.getPageSize(), page.getTotal(), list));
        }
        return new SerializeObject<>(ResultType.NORMAL, new DataTable<FrozenTbillBean>(page.getPageNum(), page.getPageSize(), page.getTotal(), new ArrayList<FrozenTbillBean>()));
    }

    @GetMapping(value = "/frozen/export")
    public void queryForFrozenExport(HttpServletResponse response, Order order, String mobile, String name, Integer startGram, Integer endGram,
                                     String startDate, String endDate) {
        mobile = UF.toString(mobile);
        name = UF.toString(name);
        startDate = UF.toString(startDate);
        endDate = UF.toString(endDate);
        startGram = startGram == null ? -1 : startGram;
        endGram = endGram == null ? -1 : endGram;
        List<FrozenTbillBean> list = payTbillService.queryForFrozenTbills(mobile, name, startGram, endGram, startDate, endDate, order.getOrder(), order.getSort(), 0, 0);
        if (list == null) {
            list = new ArrayList<FrozenTbillBean>();
        }
        String fileName = "提金提单冻结记录表";
        String[] columnNames = {"序号", "手机号", "用户姓名", "操作流水号", "冻结提单编号", "冻结提单克重（克）", "操作类型",
                "操作备注", "操作备注"};
        String[] columns = {"index", "mobile", "name", "orderNO", "tbillNO", "totalGram", "type", "remark", "addTime"};
        int index = 1;
        for (FrozenTbillBean bean : list) {
            bean.setIndex(index);
            index++;
            bean.setType("冻结");
            bean.setRemark(TbillStatusRemark.GOLD_EXTRACTION_PREBOOK.getValue());
        }
        ExportExcelController<FrozenTbillBean> export = new ExportExcelController<FrozenTbillBean>();
        export.exportExcel(fileName, fileName, columnNames, columns, list, response, ExportExcelUtil.EXCEL_FILE_2003);
    }

    @GetMapping(value = "/waiting/list")
    public SerializeObject<DataTable<WaitingPayBean>> queryForWaitingList(@RequestHeader String accessToken, Page page) {
        String memberId = LoginHelper.getLoginId();
        if (StringUtils.isBlank(memberId)) {
            return new SerializeObjectError("00000102");
        }
        int total = payTbillService.countForWaitingTbills(memberId);
        page.setTotal(total);
        if (total > 0) {
            List<WaitingPayBean> list = payTbillService.queryForWaitingTbills(memberId, PaginationUtil.getOffset(page.getPageNum(), page.getPageSize()), PaginationUtil.getPageSize(page.getPageSize()));
            return new SerializeObject<>(ResultType.NORMAL, new DataTable<WaitingPayBean>(page.getPageNum(), page.getPageSize(), page.getTotal(), list));
        }
        return new SerializeObject<>(ResultType.NORMAL, new DataTable<WaitingPayBean>(page.getPageNum(), page.getPageSize(), page.getTotal(), new ArrayList<WaitingPayBean>()));
    }

    @GetMapping(value = "/records")
    public SerializeObject<DataTable<TbillRecord>> queryForRecordsList(Page page, String productId) {
        productId = UF.toString(productId);
        int total = payTbillService.countForRecords(productId);
        page.setTotal(total);
        if (total > 0) {
            List<TbillRecord> list = payTbillService.queryForRecords(productId, PaginationUtil.getOffset(page.getPageNum(), page.getPageSize()), PaginationUtil.getPageSize(page.getPageSize()));
            return new SerializeObject<>(ResultType.NORMAL, new DataTable<TbillRecord>(page.getPageNum(), page.getPageSize(), page.getTotal(), list));
        }
        return new SerializeObject<>(ResultType.NORMAL, new DataTable<TbillRecord>(page.getPageNum(), page.getPageSize(), page.getTotal(), new ArrayList<TbillRecord>()));
    }

    @GetMapping(value = "/count/records")
    public SerializeObject queryCountForRecordsList(@RequestHeader String accessToken) {
        String memberId = LoginHelper.getLoginId();
        if (StringUtils.isBlank(memberId)) {
            return new SerializeObjectError("00000102");
        }
        int total = payTbillService.queryCountForRecordsList(memberId);
        return new SerializeObject<>(ResultType.NORMAL, total);
    }

    @GetMapping(value = "/experience/order/list")
    public SerializeObject<DataTable<PayExperienceOrder>> queryForList(@RequestHeader String accessToken, Page page, Order order, String mobile, String name,
                                                                       String startAddTime, String endAddTime, String startOverTime, String endOverTime) {
        mobile = UF.toString(mobile);
        name = UF.toString(name);
        startAddTime = UF.toString(startAddTime);
        endAddTime = UF.toString(endAddTime);
        startOverTime = UF.toString(startOverTime);
        endOverTime = UF.toString(endOverTime);
        int total = payTbillService.count(mobile, name, "", -1, startAddTime, endAddTime, startOverTime, endOverTime);
        page.setTotal(total);
        if (total > 0) {
            List<PayExperienceOrder> list = payTbillService.query(mobile, name, "", -1, startAddTime, endAddTime, startOverTime, endOverTime, order.getOrder(), order.getSort(),
                    PaginationUtil.getOffset(page.getPageNum(), page.getPageSize()), PaginationUtil.getPageSize(page.getPageSize()));
            return new SerializeObject<>(ResultType.NORMAL, new DataTable<PayExperienceOrder>(page.getPageNum(), page.getPageSize(), page.getTotal(), list));
        }
        return new SerializeObject<>(ResultType.NORMAL, new DataTable<PayExperienceOrder>(page.getPageNum(), page.getPageSize(), page.getTotal(), new ArrayList<PayExperienceOrder>()));
    }

    @GetMapping(value = "/member/experience/order/list")
    public SerializeObject<DataTable<PayExperienceOrder>> queryForList(@RequestHeader String accessToken, Page page, Integer status) {
        String memberId = LoginHelper.getLoginId();
        if (StringUtils.isBlank(memberId)) {
            return new SerializeObjectError("00000102");
        }
        status = status == null ? 1 : status;
        int total = payTbillService.count("", "", memberId, status, "", "", "", "");
        page.setTotal(total);
        if (total > 0) {
            List<PayExperienceOrder> list = payTbillService.query("", "", memberId, status, "", "", "", "", "", "",
                    PaginationUtil.getOffset(page.getPageNum(), page.getPageSize()), PaginationUtil.getPageSize(page.getPageSize()));
            return new SerializeObject<>(ResultType.NORMAL, new DataTable<PayExperienceOrder>(page.getPageNum(), page.getPageSize(), page.getTotal(), list));
        }
        return new SerializeObject<>(ResultType.NORMAL, new DataTable<PayExperienceOrder>(page.getPageNum(), page.getPageSize(), page.getTotal(), new ArrayList<PayExperienceOrder>()));
    }

    @GetMapping(value = "/member/experience/order/detail")
    public SerializeObject<PayExperienceOrder> queryForList(@RequestHeader String accessToken, String orderNO) {
        orderNO = UF.toString(orderNO);
        return new SerializeObject<>(ResultType.NORMAL, payTbillService.findByOrderNO(orderNO));
    }

    @GetMapping(value = "/experience/order/export")
    public void queryForExport(HttpServletResponse response, Page page, Order order, String mobile, String name,
                               String startAddTime, String endAddTime, String startOverTime, String endOverTime) {
        mobile = UF.toString(mobile);
        name = UF.toString(name);
        startAddTime = UF.toString(startAddTime);
        endAddTime = UF.toString(endAddTime);
        startOverTime = UF.toString(startOverTime);
        endOverTime = UF.toString(endOverTime);
        List<PayExperienceOrder> list = payTbillService.query(mobile, name, "", -1, startAddTime, endAddTime, startOverTime, endOverTime, order.getOrder(), order.getSort(), 0, 0);
        if (list == null) {
            list = new ArrayList<PayExperienceOrder>();
        }
        String fileName = "体验金购买记录表";
        String[] columnNames = {"序号", "手机号", "用户姓名", "体验金提单编号", "购买时间", "产品名称", "产品状态", "产品克重（克）", "回租期限（天）", "回租时价格（元/克）",
                "年化收益（%）", "回租开始时间", "回租到期时间", "体验金奖励克重（克）", "折算金额（元）", "对应金豆（个）", "奖励到账时间"};
        String[] columns = {"index", "mobile", "name", "orderNO", "addTime", "productName", "statusMark", "totalGram", "leasebackDays", "goldPrice",
                "yearIncome", "startTime", "endTime", "incomeGram", "incomeAmount", "incomeBean", "modifyTime"};
        int index = 1;
        for (PayExperienceOrder bean : list) {
            bean.setIndex(index);
            index++;
            if (bean.getStatus() == 1) {
                bean.setStatusMark(TbillStatusEnum.LEASEBACK.getRemark());
            } else if (bean.getStatus() == 2) {
                bean.setStatusMark(TbillStatusEnum.PAST.getRemark());
            }
        }
        ExportExcelController<PayExperienceOrder> export = new ExportExcelController<PayExperienceOrder>();
        export.exportExcel(fileName, fileName, columnNames, columns, list, response, ExportExcelUtil.EXCEL_FILE_2003);
    }

    private PayTbillStatistic converListToBean(List<PayTbill> list) {
        PayTbillStatistic payTbillStatistic = new PayTbillStatistic();
        if (!CollectionUtils.isEmpty(list)) {
            try {
                //合计人数
                List<PayTbill> filterList = list.stream().filter(o -> o.getMemberId() != null).collect(
                        Collectors.collectingAndThen(
                                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(PayTbill::getMemberId))), ArrayList::new));
                payTbillStatistic.setCountPersonNum(filterList.size());
                //合计笔数
                payTbillStatistic.setCountNum(list.size());
                //合计购买克重
                int totalGram = list.stream().mapToInt(PayTbill::getTotalGram).sum();
                payTbillStatistic.setTotalGram(totalGram);
                //合计够买提单金额
                BigDecimal totalAmount = list.stream().map(PayTbill::getTotalAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                payTbillStatistic.setTotalAmount(totalAmount);
                //合计金豆抵扣
                BigDecimal totalBeanGram = list.stream().filter(o -> o.getBeanGram() != null).map(PayTbill::getBeanGram).reduce(BigDecimal.ZERO, BigDecimal::add);
                payTbillStatistic.setTotalBeanGram(totalBeanGram);
                //合计使用抵扣卷
                BigDecimal totalCouponGram = list.stream().filter(o -> o.getCouponGram() != null).map(PayTbill::getCouponGram).reduce(BigDecimal.ZERO, BigDecimal::add);
                payTbillStatistic.setTotalCouponGram(totalCouponGram);
                //合计实际支付克重
                BigDecimal totalPayGram = list.stream().map(PayTbill::getPayGram).reduce(BigDecimal.ZERO, BigDecimal::add);
                payTbillStatistic.setTotalPayGram(totalPayGram);
                //合计实际支付金额
                BigDecimal totalPayAmount = list.stream().map(PayTbill::getPayAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                payTbillStatistic.setTotalPayAmount(totalPayAmount);
            } catch (Exception e) {
                log.info("提单生成记录统计出错：" + e.getStackTrace());
            }
        }
        return payTbillStatistic;
    }

    private PayTbillLeasebackStatistic converLeasebackListToBean(List<PayTbillLeaseback> list) {
        PayTbillLeasebackStatistic payTbillLeasebackStatistic = new PayTbillLeasebackStatistic();
        if (!CollectionUtils.isEmpty(list)) {
            try {
                //合计人数
                List<PayTbillLeaseback> filterList = list.stream().filter(o -> o.getMemberId() != null).collect(
                        Collectors.collectingAndThen(
                                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(PayTbillLeaseback::getMemberId))), ArrayList::new));
                payTbillLeasebackStatistic.setCountPersonNum(filterList.size());
                //合计笔数
                payTbillLeasebackStatistic.setCountNum(list.size());

                //合计回租中提单克重
                int totalGram = list.stream().mapToInt(PayTbillLeaseback::getTotalGram).sum();
                payTbillLeasebackStatistic.setTotalGram(totalGram);

                //合计回租中提单金额
                BigDecimal totalAmount = list.stream().map(PayTbillLeaseback::getTotalMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
                payTbillLeasebackStatistic.setTotalAmount(totalAmount);

                //合计对应金豆
                Integer totalBean = list.stream().mapToInt(PayTbillLeaseback::getIncomeBeans).sum();
                payTbillLeasebackStatistic.setTotalBean(totalBean);

                //金生金奖励
                BigDecimal totalGoldGiveGoldAmount = list.stream().map(PayTbillLeaseback::getGoldGiveGoldAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                payTbillLeasebackStatistic.setTotalGoldGiveGoldAmount(totalGoldGiveGoldAmount);

                //合计黄金红包额度
                Integer totalCouponAmount = list.stream().mapToInt(PayTbillLeaseback::getCouponAmount).sum();
                payTbillLeasebackStatistic.setTotalCouponAmount(totalCouponAmount);

                //合计黄金红包奖励
                BigDecimal totalCouponAwardAmount = list.stream().filter(o -> o.getCouponAwardAmount() != null).map(PayTbillLeaseback::getCouponAwardAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                payTbillLeasebackStatistic.setTotalCouponAwardAmount(totalCouponAwardAmount);

                //合计回租专享优惠
                BigDecimal totalDiscountAmount = list.stream().filter(o -> o.getDiscountAmount() != null).map(PayTbillLeaseback::getDiscountAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                payTbillLeasebackStatistic.setTotalDiscountAmount(totalDiscountAmount);

                //合计回租总奖励
                BigDecimal totalIncomeAmount = list.stream().filter(o -> o.getIncomeAmount() != null).map(PayTbillLeaseback::getIncomeAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                payTbillLeasebackStatistic.setTotalIncomeAmount(totalIncomeAmount);
            } catch (Exception e) {
                log.info("回租中提单记录统计出错：" + e.getMessage());
            }
        }
        return payTbillLeasebackStatistic;
    }


    private PayTbillSoldStatistic converSoldListToBean(List<PayTbillSold> list) {
        PayTbillSoldStatistic payTbillSoldStatistic = new PayTbillSoldStatistic();
        if (!CollectionUtils.isEmpty(list)) {
            try {
                List<PayTbillSold> filterList = list.stream().filter(o -> o.getMemberId() != null).collect(
                        Collectors.collectingAndThen(
                                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(PayTbillSold::getMemberId))), ArrayList::new));
                payTbillSoldStatistic.setCountPersonNum(filterList.size());

                //合计笔数
                payTbillSoldStatistic.setCountNum(list.size());

                //合计出售提单克重
                int totalGram = list.stream().mapToInt(PayTbillSold::getTotalGram).sum();
                payTbillSoldStatistic.setTotalGram(totalGram);


                //合计出售提单金额
                BigDecimal totalAmount = list.stream().filter(o -> o.getTotalAmount() != null).map(PayTbillSold::getTotalAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                payTbillSoldStatistic.setTotalAmount(totalAmount);


                //合计出售手续费
                BigDecimal totalFee = list.stream().filter(o -> o.getFee() != null).map(PayTbillSold::getFee).reduce(BigDecimal.ZERO, BigDecimal::add);
                payTbillSoldStatistic.setTotalFee(totalFee);

                //合计出售扣减已优惠金额
                BigDecimal totalCouponAmount = list.stream().filter(o -> o.getCouponAmount() != null).map(PayTbillSold::getCouponAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                payTbillSoldStatistic.setTotalCouponAmount(totalCouponAmount);

                //出售到账金额
                BigDecimal totalActualAmount = list.stream().filter(o -> o.getActualAmount() != null).map(PayTbillSold::getActualAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                payTbillSoldStatistic.setTotalActualAmount(totalActualAmount);
            } catch (Exception e) {
                log.info("已出售提单记录统计出错：" + e.getMessage());
            }
        }
        return payTbillSoldStatistic;
    }

    private Map converSoldIncomeListToMap(List<PayTbillSold> list) {
        Map map = new HashMap();
        if (!CollectionUtils.isEmpty(list)) {
            try {
                List<PayTbillSold> filterList = list.stream().filter(o -> o.getMemberId() != null).collect(
                        Collectors.collectingAndThen(
                                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(PayTbillSold::getMemberId))), ArrayList::new));
                map.put("countPersonNum",filterList.size());
                map.put("countNum",list.size());

                //合计出售提单克重
                int totalGram = list.stream().mapToInt(PayTbillSold::getTotalGram).sum();
                map.put("totalGram",totalGram);

                //合计购买时提单金额
                BigDecimal buyTotalAmount = list.stream().filter(o -> o.getBuyTotalAmount() != null).map(PayTbillSold::getBuyTotalAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                map.put("buyTotalAmount",buyTotalAmount);

                //合计出售提单金额
                BigDecimal totalAmount = list.stream().filter(o -> o.getTotalAmount() != null).map(PayTbillSold::getTotalAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                map.put("totalAmount",totalAmount);

                //合计出售换取差价
                BigDecimal incomeAmount = list.stream().filter(o -> o.getIncomeAmount() != null).map(PayTbillSold::getIncomeAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                map.put("incomeAmount",incomeAmount);
            } catch (Exception e) {
                log.info("提单涨幅收益统计出错：" + e.getMessage());
            }
        }
        return map;
    }

    private Map converAgainLeasebackToMap(List<PayTbillAgainLeaseback> list) {
        Map map = new HashMap();
        if (!CollectionUtils.isEmpty(list)) {
            try {
                List<PayTbillAgainLeaseback> filterList = list.stream().filter(o -> o.getMemberId() != null).collect(
                        Collectors.collectingAndThen(
                                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(PayTbillAgainLeaseback::getMemberId))), ArrayList::new));
                map.put("countPersonNum",filterList.size());
                List<PayTbillAgainLeaseback> nameList = list.stream().filter(o -> o.getName() != null).collect(
                        Collectors.collectingAndThen(
                                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(PayTbillAgainLeaseback::getName))), ArrayList::new));
                List<PayTbillAgainLeaseback> mobileList = list.stream().filter(o -> o.getMobile() != null).collect(
                        Collectors.collectingAndThen(
                                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(PayTbillAgainLeaseback::getMobile))), ArrayList::new));
                List<PayTbillAgainLeaseback> tbillNoList = list.stream().filter(o -> o.getTbillNo() != null).collect(
                        Collectors.collectingAndThen(
                                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(PayTbillAgainLeaseback::getTbillNo))), ArrayList::new));
                List<PayTbillAgainLeaseback> orderNoList = list.stream().filter(o -> o.getOrderNo() != null).collect(
                        Collectors.collectingAndThen(
                                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(PayTbillAgainLeaseback::getOrderNo))), ArrayList::new));
                map.put("tbillNoCount",tbillNoList.size());
                map.put("orderNoCount",orderNoList.size());
                map.put("nameCount",filterList.size());
                map.put("mobileCount",filterList.size());
                //合计出售提单克重
                //复投提单：一笔提单多次复投的提单，列表显示从第二次回租的记录
                int totalGram = list.stream().mapToInt(PayTbillAgainLeaseback::getTotalGram).sum();
                map.put("totalGram",totalGram);

                //合计购买时提单金额
                BigDecimal totalAmount = list.stream().filter(o -> o.getTotalAmount() != null).map(PayTbillAgainLeaseback::getTotalAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                map.put("totalAmount",totalAmount);

            } catch (Exception e) {
                log.info("提单复投记录统计出错：" + e.getMessage());
            }
        }
        return map;
    }

    /**
     * 获取平台累计回租总克重
     * @return
     */
    @RequestMapping(value="/findPlatformGram" , method = GET)
    public SerializeObject findPlatformTotalGram() {
        Integer totalGram = payTbillLeasebackService.findPlatformLeasebackTotalGram();
        return new SerializeObject<>(ResultType.NORMAL, totalGram);
    }

    /**
     *
     * app端-获取投资动态
     * @return
     */
    @RequestMapping(value = "/findInvestList", method = GET)
    public SerializeObject findInvestList() {
        SerializeObject data = rateSettingsService.findInvest();
        if (null != data && null != data.getData()) {
            Map map = new HashMap();
            //读取条数
            int redNum = 0;
            InvestBoardBean investBoardBean = JSON.parseObject(JSONObject.toJSONString(data.getData()), InvestBoardBean.class);
            if (investBoardBean != null && investBoardBean.getInvestReadNum() > 0) {
                redNum = investBoardBean.getInvestReadNum();
            }
            map.put("redNum",redNum);
            //截至时间UF.getFormatDateNow();
            map.put("endTime",UF.getFormatDateNow());
            return payTbillService.findInvestList(map);
        }
        return new SerializeObject<>(ResultType.NORMAL, new ArrayList<>());
    }

}